mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
Compare commits
126
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f475ae983e | ||
|
|
3be57f609e | ||
|
|
fc66e2f78b | ||
|
|
1afadaa142 | ||
|
|
1583b74c9d | ||
|
|
e8ba07ee43 | ||
|
|
7f706d398f | ||
|
|
7b50be4afb | ||
|
|
f690e124d0 | ||
|
|
df6e87f552 | ||
|
|
45305bf78f | ||
|
|
e6f640c53d | ||
|
|
4f1d39ed0e | ||
|
|
a7570926c9 | ||
|
|
aa481d7463 | ||
|
|
e79afa5b65 | ||
|
|
b69a80db90 | ||
|
|
5f64b680f5 | ||
|
|
a3508be54a | ||
|
|
0fede5f475 | ||
|
|
a8c36b9654 | ||
|
|
8c98287b39 | ||
|
|
345fa9c3ac | ||
|
|
cf483e0237 | ||
|
|
f40710f500 | ||
|
|
9f162d813f | ||
|
|
3edee14eea | ||
|
|
82757763e6 | ||
|
|
91346a814d | ||
|
|
5f013ad41d | ||
|
|
00cd5490c4 | ||
|
|
a4542cf71b | ||
|
|
f4521da771 | ||
|
|
6ba0f3622a | ||
|
|
e3765e24e1 | ||
|
|
7171bf1005 | ||
|
|
b85ee3217d | ||
|
|
12f137c645 | ||
|
|
f0eb798f7e | ||
|
|
5c60351288 | ||
|
|
5895aca2c5 | ||
|
|
cfd2469f8b | ||
|
|
0094a5dba4 | ||
|
|
94e84fc9b8 | ||
|
|
35ad2c5cdc | ||
|
|
af7e0a700b | ||
|
|
8943449825 | ||
|
|
555488e0bb | ||
|
|
c6cf9da861 | ||
|
|
f11e9253b2 | ||
|
|
fac68e4838 | ||
|
|
17d8105c38 | ||
|
|
a31eed376c | ||
|
|
e8abd881d2 | ||
|
|
136b5c936d | ||
|
|
34855d000e | ||
|
|
b6eed01e41 | ||
|
|
9616fb4cd7 | ||
|
|
344d8ba217 | ||
|
|
7e5239aff0 | ||
|
|
09d5225883 | ||
|
|
7f3ba14cec | ||
|
|
850414b358 | ||
|
|
f18fa672f2 | ||
|
|
fcb62348b9 | ||
|
|
fbbb31bc49 | ||
|
|
4d0e574ba4 | ||
|
|
ce5b56fdf7 | ||
|
|
04de7f7498 | ||
|
|
46b2165312 | ||
|
|
4182951b19 | ||
|
|
cbd6f247d9 | ||
|
|
73facc313e | ||
|
|
d2e3094544 | ||
|
|
61512d5b8f | ||
|
|
2b42038c09 | ||
|
|
ad8f6ccda3 | ||
|
|
a201c9b3f3 | ||
|
|
7edde650a1 | ||
|
|
ae3b88f23b | ||
|
|
c86e58e5e8 | ||
|
|
f441432d57 | ||
|
|
417982862e | ||
|
|
158733df8f | ||
|
|
4b75870857 | ||
|
|
dbfe86f018 | ||
|
|
f7d95acec8 | ||
|
|
506686cfb7 | ||
|
|
8415a591e1 | ||
|
|
1f8644f059 | ||
|
|
f32f947b62 | ||
|
|
99ce717f7e | ||
|
|
28f32a2f6d | ||
|
|
3d5d730306 | ||
|
|
96426de56f | ||
|
|
b14b5e3622 | ||
|
|
35cd6ea336 | ||
|
|
3332870e9e | ||
|
|
944c4bb2f2 | ||
|
|
705faf4a78 | ||
|
|
614eda3b08 | ||
|
|
593cf6a533 | ||
|
|
17ddae5db4 | ||
|
|
d1b1eb65b6 | ||
|
|
43ee74a2e0 | ||
|
|
20d33ac699 | ||
|
|
1609e9211f | ||
|
|
c8c05e9d0b | ||
|
|
35130122e4 | ||
|
|
c1b549867a | ||
|
|
efea823ef1 | ||
|
|
91e375693c | ||
|
|
022aa38ad1 | ||
|
|
40419fb891 | ||
|
|
25d4a3b439 | ||
|
|
968e8d3d66 | ||
|
|
6610938b80 | ||
|
|
4b2691f572 | ||
|
|
0ac2532fe5 | ||
|
|
e42892cb90 | ||
|
|
0d14a559eb | ||
|
|
2a65fcb388 | ||
|
|
a02b9d953a | ||
|
|
53f8c36587 | ||
|
|
8323f5b4ad | ||
|
|
6ef349a6d4 |
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
|
||||
|
||||
|
||||
+25
-12
@@ -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 \
|
||||
@@ -24,15 +32,13 @@ EXTRA_DIST = \
|
||||
AM_CXXFLAGS = -I./code @D_CFLAGS@
|
||||
AM_LDFLAGS = @D_LDFLAGS@
|
||||
|
||||
EXTRA_PROGRAMS = cfilearchiver cfileextractor
|
||||
EXTRA_PROGRAMS = cfilearchiver cfileextractor cryptstring scramble
|
||||
|
||||
###############################################################################
|
||||
##
|
||||
## Begin utilitites
|
||||
##
|
||||
|
||||
CPPSOURCES=$(wildcard code/*/*.cpp code/*/*.h)
|
||||
|
||||
# cfilearchiver -- to create VPs
|
||||
cfilearchiver_SOURCES = \
|
||||
code/cfilearchiver/cfilearchiver.cpp
|
||||
@@ -41,18 +47,25 @@ cfilearchiver_SOURCES = \
|
||||
cfileextractor_SOURCES = \
|
||||
code/cfileextractor/cfileextractor.cpp
|
||||
|
||||
# cryptstring -- to encrypt strings that are used as cheat codes
|
||||
cryptstring_SOURCES = \
|
||||
code/cryptstring/cryptstring.cpp
|
||||
|
||||
# scramble -- to encrypt tables
|
||||
scramble_SOURCES = \
|
||||
code/parse/encrypt.cpp \
|
||||
code/scramble/scramble.cpp \
|
||||
code/scramble/scramble.h
|
||||
|
||||
|
||||
# catch all to build utilitites
|
||||
tools: cfilearchiver cfileextractor
|
||||
tools: cfilearchiver cfileextractor cryptstring scramble
|
||||
|
||||
|
||||
# cleaning
|
||||
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,10 +1,7 @@
|
||||
The "projects" directory contains ready projects for:
|
||||
Microsoft Visual C++ 6
|
||||
Microsoft Visual C++ 2005
|
||||
Microsoft Visual C++ 2008
|
||||
Micrsofot Visual C++ 2010
|
||||
Apple Xcode
|
||||
Code::Blocks
|
||||
Anjuta 1 (please see README with project before using)
|
||||
|
||||
|
||||
See the ChangeLog to see what's new.
|
||||
|
||||
@@ -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
|
||||
+211
-185
@@ -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
|
||||
@@ -511,178 +712,3 @@ int main ()
|
||||
AC_SUBST(THEORA_LIBS)
|
||||
rm -f conf.theoratest
|
||||
])
|
||||
|
||||
|
||||
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 Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(openal,[ --with-openal=PFX Prefix where OpenAL is installed (optional)], openal_prefix="$withval", openal_prefix="")
|
||||
AC_ARG_WITH(openal-libraries,[ --with-openal-libraries=DIR Directory where OpenAL library is installed (optional)], openal_libraries="$withval", openal_libraries="")
|
||||
AC_ARG_WITH(openal-includes,[ --with-openal-includes=DIR Directory where OpenAL header files are installed (optional)], openal_includes="$withval", openal_includes="")
|
||||
AC_ARG_ENABLE(openaltest, [ --disable-openaltest Do not try to compile and run a test OpenAL program],, enable_openaltest=yes)
|
||||
|
||||
if test "x$openal_libraries" != "x" ; then
|
||||
OPENAL_LIBS="-L$openal_libraries"
|
||||
elif test "x$openal_prefix" != "x" ; then
|
||||
OPENAL_LIBS="-L$openal_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENAL_LIBS="-L$libdir"
|
||||
fi
|
||||
|
||||
OPENAL_LIBS="$OPENAL_LIBS -lopenal"
|
||||
|
||||
if test "x$openal_includes" != "x" ; then
|
||||
OPENAL_CFLAGS="-I$openal_includes"
|
||||
elif test "x$openal_prefix" != "x" ; then
|
||||
OPENAL_CFLAGS="-I$openal_prefix/include"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENAL_CFLAGS=""
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING(for OpenAL)
|
||||
no_openal=""
|
||||
|
||||
|
||||
if test "x$enable_openaltest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $OPENAL_CFLAGS"
|
||||
LIBS="$LIBS $OPENAL_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed OpenAL is sufficiently new.
|
||||
dnl
|
||||
rm -f conf.openaltest
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
#ifdef AL_VERSION_1_1
|
||||
alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT");
|
||||
|
||||
system("touch conf.openaltest");
|
||||
return 0;
|
||||
#else
|
||||
printf("\n*** OpenAL version 1.1 or greater is required.\n");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
],, no_openal=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_openal" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.openaltest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run OpenAL test program, checking why..."
|
||||
CFLAGS="$CFLAGS $OPENAL_CFLAGS"
|
||||
LIBS="$LIBS $OPENAL_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <stdio.h>
|
||||
#include <AL/al.h>
|
||||
], [ return 0; ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding OpenAL or finding the wrong"
|
||||
echo "*** version of OpenAL. If it is not finding OpenAL, you'll need to set your"
|
||||
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
|
||||
echo "*** to the installed location Also, make sure you have run ldconfig if that"
|
||||
echo "*** is required on your system"
|
||||
echo "***"
|
||||
echo "*** If you have an old version installed, it is best to remove it, although"
|
||||
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
|
||||
[ echo "*** The test program failed to compile or link. See the file config.log for the"
|
||||
echo "*** exact error that occured. This usually means OpenAL was incorrectly installed"
|
||||
echo "*** or that you have moved OpenAL since it was installed." ])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
OPENAL_CFLAGS=""
|
||||
OPENAL_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_SUBST(OPENAL_CFLAGS)
|
||||
AC_SUBST(OPENAL_LIBS)
|
||||
rm -f conf.openaltest
|
||||
])
|
||||
|
||||
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 Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(opengl,[ --with-opengl=PFX Prefix where OpenGL is installed (optional)], opengl_prefix="$withval", opengl_prefix="")
|
||||
AC_ARG_WITH(opengl-libraries,[ --with-opengl-libraries=DIR Directory where OpenGL library is installed (optional)], opengl_libraries="$withval", opengl_libraries="")
|
||||
AC_ARG_WITH(opengl-includes,[ --with-opengl-includes=DIR Directory where OpenGL header files are installed (optional)], opengl_includes="$withval", opengl_includes="")
|
||||
AC_ARG_ENABLE(opengltest, [ --disable-opengltest Do not try to compile and run a test OpenGL program],, enable_opengltest=yes)
|
||||
|
||||
if test "x$opengl_libraries" != "x" ; then
|
||||
OPENGL_LIBS="-L$opengl_libraries"
|
||||
elif test "x$opengl_prefix" != "x" ; then
|
||||
OPENGL_LIBS="-L$opengl_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENGL_LIBS="-L$libdir"
|
||||
fi
|
||||
|
||||
OPENGL_LIBS="$OPENGL_LIBS -lGL -lGLU"
|
||||
|
||||
if test "x$opengl_includes" != "x" ; then
|
||||
OPENGL_CFLAGS="-I$opengl_includes"
|
||||
elif test "x$opengl_prefix" != "x" ; then
|
||||
OPENGL_CFLAGS="-I$opengl_prefix/include"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENGL_CFLAGS=""
|
||||
fi
|
||||
|
||||
|
||||
no_opengl=""
|
||||
|
||||
|
||||
if test "x$enable_opengltest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $OPENGL_CFLAGS"
|
||||
LIBS="$LIBS $OPENGL_LIBS"
|
||||
|
||||
AC_CHECK_LIB(GL, glPushMatrix,
|
||||
[AC_CHECK_HEADER(GL/gl.h,
|
||||
[AC_CHECK_LIB(GLU, gluPerspective,
|
||||
[AC_CHECK_HEADER(GL/glu.h, ,
|
||||
dnl NOTE: this is a failure
|
||||
no_opengl=yes
|
||||
)]
|
||||
)]
|
||||
)]
|
||||
)
|
||||
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_opengl" = "x" ; then
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
OPENGL_CFLAGS=""
|
||||
OPENGL_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_SUBST(OPENGL_CFLAGS)
|
||||
AC_SUBST(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
-9
@@ -110,26 +110,24 @@ 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
|
||||
|
||||
#conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
|
||||
|
||||
# to not run configure, call autogen.sh as,
|
||||
# NOCONFIGURE=1 ./autogen.sh
|
||||
if test x$NOCONFIGURE = x; then
|
||||
echo Running $srcdir/configure $conf_flags "$@" ...
|
||||
$srcdir/configure $conf_flags "$@" \
|
||||
|
||||
@@ -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
|
||||
+67
-127
@@ -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,13 @@ 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 \
|
||||
decals/decals.cpp \
|
||||
decals/decals.h \
|
||||
demo/demo.cpp \
|
||||
demo/demo.h \
|
||||
exceptionhandler/exceptionhandler.cpp \
|
||||
exceptionhandler/exceptionhandler.h \
|
||||
external_dll/externalcode.h \
|
||||
@@ -293,13 +289,12 @@ FS2_SOURCES = \
|
||||
gamesnd/gamesnd.h \
|
||||
globalincs/alphacolors.cpp \
|
||||
globalincs/alphacolors.h \
|
||||
globalincs/crypt.cpp \
|
||||
globalincs/crypt.h \
|
||||
globalincs/def_files.cpp \
|
||||
globalincs/def_files.h \
|
||||
globalincs/fsmemory.cpp \
|
||||
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 +335,6 @@ FS2_SOURCES = \
|
||||
graphics/grstub.cpp \
|
||||
graphics/grstub.h \
|
||||
graphics/line.h \
|
||||
graphics/shadows.cpp \
|
||||
graphics/tmapper.h \
|
||||
hud/hud.cpp \
|
||||
hud/hud.h \
|
||||
@@ -365,6 +359,7 @@ FS2_SOURCES = \
|
||||
hud/hudobserver.h \
|
||||
hud/hudparse.cpp \
|
||||
hud/hudparse.h \
|
||||
hud/hudresource.h \
|
||||
hud/hudreticle.cpp \
|
||||
hud/hudreticle.h \
|
||||
hud/hudshield.cpp \
|
||||
@@ -385,8 +380,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 +472,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 +492,6 @@ FS2_SOURCES = \
|
||||
model/modelsinc.h \
|
||||
model/modeloctant.cpp \
|
||||
model/modelread.cpp \
|
||||
model/modelrender.cpp \
|
||||
nebula/neb.cpp \
|
||||
nebula/neb.h \
|
||||
nebula/neblightning.cpp \
|
||||
@@ -534,6 +528,7 @@ FS2_SOURCES = \
|
||||
network/multi_obj.h \
|
||||
network/multi_observer.cpp \
|
||||
network/multi_observer.h \
|
||||
network/multi_oo.h \
|
||||
network/multi_options.cpp \
|
||||
network/multi_options.h \
|
||||
network/multi_pause.cpp \
|
||||
@@ -559,6 +554,8 @@ FS2_SOURCES = \
|
||||
network/multi_voice.h \
|
||||
network/multi_xfer.cpp \
|
||||
network/multi_xfer.h \
|
||||
network/psnet.cpp \
|
||||
network/psnet.h \
|
||||
network/psnet2.cpp \
|
||||
network/psnet2.h \
|
||||
network/stand_gui.cpp \
|
||||
@@ -588,20 +585,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 +601,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 \
|
||||
@@ -636,8 +615,6 @@ FS2_SOURCES = \
|
||||
popup/popupdead.h \
|
||||
radar/radar.cpp \
|
||||
radar/radar.h \
|
||||
radar/radardradis.cpp \
|
||||
radar/radardradis.h \
|
||||
radar/radarorb.cpp \
|
||||
radar/radarorb.h \
|
||||
radar/radarsetup.cpp \
|
||||
@@ -757,8 +734,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 +754,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 +797,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 +825,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
|
||||
##
|
||||
|
||||
+19
-26
@@ -7,26 +7,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The code in here is just for bookeeping, allocating AI slots and linking them to ships.
|
||||
* See AiCode.cpp for the actual AI code.
|
||||
*/
|
||||
// The code in here is just for bookeeping, allocating
|
||||
// ai slots and linking them to ships.
|
||||
// See AiCode.cpp for the actual AI code.
|
||||
|
||||
#include "ai/ai.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
|
||||
int Total_goal_target_names = 0;
|
||||
char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
|
||||
|
||||
int Total_goal_ship_names = 0;
|
||||
char Goal_ship_names[MAX_GOAL_SHIP_NAMES][NAME_LENGTH];
|
||||
ai_info Ai_info[MAX_AI_INFO];
|
||||
ai_info *Player_ai;
|
||||
|
||||
/**
|
||||
* @brief Returns index of free AI slot.
|
||||
* @return Return -1 if no free slot.
|
||||
*/
|
||||
// Return index of free AI slot.
|
||||
// Return -1 if no free slot.
|
||||
int ai_get_slot(int shipnum)
|
||||
{
|
||||
int i;
|
||||
@@ -43,10 +40,8 @@ int ai_get_slot(int shipnum)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees a currently used AI slot.
|
||||
* @details Only modifies in ::Ai_info struct. Does not modify hook in ship.
|
||||
*/
|
||||
// Releases an AI slot to be used by someone else.
|
||||
// Only modifies in Ai_info struct. Does not modify hook in ship.
|
||||
void ai_free_slot(int ai_index)
|
||||
{
|
||||
Assert( (ai_index >= 0) && (ai_index < MAX_AI_INFO) );
|
||||
@@ -82,22 +77,20 @@ 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_ship_name(char *name, int *index)
|
||||
{
|
||||
Assert(name != NULL);
|
||||
Assert(index != NULL);
|
||||
int i;
|
||||
|
||||
for (i=0; i < Total_goal_target_names; i++)
|
||||
if (!stricmp(name, Goal_target_names[i])) {
|
||||
for (i=0; i < Total_goal_ship_names; i++)
|
||||
if (!stricmp(name, Goal_ship_names[i])) {
|
||||
*index = i;
|
||||
return Goal_target_names[i];
|
||||
return Goal_ship_names[i];
|
||||
}
|
||||
|
||||
Assert(Total_goal_target_names < MAX_GOAL_TARGET_NAMES);
|
||||
Assertion(strlen(name) <= NAME_LENGTH - 1, "Goal target name %s is too long. Needs to be 31 characters or less.", name);
|
||||
i = Total_goal_target_names++;
|
||||
strcpy_s(Goal_target_names[i], name);
|
||||
Assert(Total_goal_ship_names < MAX_GOAL_SHIP_NAMES);
|
||||
Assertion(strlen(name) < NAME_LENGTH - 1, "Ship name %s is too long. Needs to be 31 characters or less.", name);
|
||||
i = Total_goal_ship_names++;
|
||||
strcpy_s(Goal_ship_names[i], name);
|
||||
*index = i;
|
||||
return Goal_target_names[i];
|
||||
return Goal_ship_names[i];
|
||||
}
|
||||
+53
-77
@@ -12,29 +12,19 @@
|
||||
#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"
|
||||
|
||||
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.
|
||||
@@ -42,11 +32,11 @@ extern ai_flag_name Ai_flag_names[];
|
||||
#define AIF_SEEK_LOCK (1 << 4) // set if should focus on gaining aspect lock, not hitting with lasers
|
||||
#define AIF_FORMATION_OBJECT (1 << 5) // Fly in formation off a specific object.
|
||||
#define AIF_TEMPORARY_IGNORE (1 << 6) // Means current ignore_objnum is only temporary, not an order from the player.
|
||||
#define AIF_USE_EXIT_PATH (1 << 7) // Used by path code, to flag path as an exit path
|
||||
#define AIF_USE_STATIC_PATH (1 << 8) // Used by path code, use fixed path, don't try to recreate
|
||||
#define AIF_USE_EXIT_PATH (1 << 7) // Used by path code, to flag path as an exit path
|
||||
#define AIF_USE_STATIC_PATH (1 << 8) // Used by path code, use fixed path, don't try to recreate
|
||||
#define AIF_TARGET_COLLISION (1 << 9) // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so.
|
||||
#define AIF_UNLOAD_SECONDARIES (1 << 10) // Fire secondaries as fast as possible!
|
||||
#define AIF_ON_SUBSYS_PATH (1 << 11) // Current path leads to a subsystem
|
||||
#define AIF_ON_SUBSYS_PATH (1 << 11) // Current path leads to a subsystem
|
||||
#define AIF_AVOID_SHOCKWAVE_SHIP (1 << 12) // Avoid an existing shockwave from a ship.
|
||||
#define AIF_AVOID_SHOCKWAVE_WEAPON (1 << 13) // Avoid an expected shockwave from a weapon. shockwave_object field contains object index.
|
||||
#define AIF_AVOID_SHOCKWAVE_STARTED (1 << 14) // Already started avoiding shockwave, don't keep deciding whether to avoid.
|
||||
@@ -58,20 +48,18 @@ extern ai_flag_name Ai_flag_names[];
|
||||
#define AIF_AVOIDING_BIG_SHIP (1 << 20) // Avoiding a large ship.
|
||||
#define AIF_BIG_SHIP_COLLIDE_RECOVER_1 (1 << 21) // Collided into a big ship. Recovering by flying away.
|
||||
#define AIF_BIG_SHIP_COLLIDE_RECOVER_2 (1 << 22) // Collided into a big ship. Fly towards big ship sphere perimeter.
|
||||
#define AIF_STEALTH_PURSUIT (1 << 23) // AI is trying to fight stealth ship
|
||||
#define AIF_STEALTH_PURSUIT (1 << 23) // Ai is trying to fight stealth ship
|
||||
|
||||
// Goober5000
|
||||
#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)
|
||||
|
||||
// dock_orient_and_approach() modes.
|
||||
#define DOA_APPROACH 1 // Approach the current point on the path (aip->path_cur)
|
||||
#define DOA_DOCK 2 // Dock with goal object.
|
||||
#define DOA_DOCK 2 // Dock with goal object.
|
||||
#define DOA_UNDOCK_1 3 // Begin undocking with goal object. Just move away.
|
||||
#define DOA_UNDOCK_2 4 // Secondary undocking. Move away.
|
||||
#define DOA_UNDOCK_3 5 // Tertiary undocking. Move away and orient away.
|
||||
@@ -85,7 +73,7 @@ extern ai_flag_name Ai_flag_names[];
|
||||
// Submodes for seeking safety.
|
||||
#define AISS_1 41 // Pick a spot to fly to.
|
||||
#define AISS_2 42 // Flying to spot.
|
||||
#define AISS_3 43 // Gotten near spot, fly about there.
|
||||
#define AISS_3 43 // Gotten near spot, fly about there.
|
||||
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2
|
||||
|
||||
#define MAX_AI_GOALS 5
|
||||
@@ -94,8 +82,8 @@ extern ai_flag_name Ai_flag_names[];
|
||||
// have priority over others (i.e. when a player issues a goal to a wing, then a seperate
|
||||
// goal to a ship in that wing). We would probably use this type in conjunction with
|
||||
// goal priority to establish which goal to follow
|
||||
#define AIG_TYPE_EVENT_SHIP 1 // from mission event direct to ship
|
||||
#define AIG_TYPE_EVENT_WING 2 // from mission event direct to wing
|
||||
#define AIG_TYPE_EVENT_SHIP 1 // from mission event direct to ship
|
||||
#define AIG_TYPE_EVENT_WING 2 // from mission event direct to wing
|
||||
#define AIG_TYPE_PLAYER_SHIP 3 // from player direct to ship
|
||||
#define AIG_TYPE_PLAYER_WING 4 // from player direct to wing
|
||||
#define AIG_TYPE_DYNAMIC 5 // created on the fly
|
||||
@@ -108,8 +96,7 @@ extern ai_flag_name Ai_flag_names[];
|
||||
#define AIGF_GOAL_OVERRIDE (1<<4) // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal
|
||||
#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_SOUND_PLAYED (1<<7) // Goober5000 - replacement for AL's hack ;)
|
||||
|
||||
#define AIGF_DOCK_INDEXES_VALID (AIGF_DOCKER_INDEX_VALID|AIGF_DOCKEE_INDEX_VALID)
|
||||
|
||||
@@ -139,12 +126,10 @@ typedef struct ai_goal {
|
||||
int flags; // one of the AIGF_* values above
|
||||
fix time; // time at which this goal was issued.
|
||||
int priority; // how important is this goal -- number 0 - 100
|
||||
|
||||
char *target_name; // name of the thing that this goal acts upon
|
||||
int target_name_index; // index of goal_target_name in Goal_target_names[][]
|
||||
waypoint_list *wp_list; // waypoints that this ship might fly.
|
||||
int target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!)
|
||||
int target_signature; // signature of object this ship might be chasing (currently only used for weapons; paired with above value to confirm target)
|
||||
char *ship_name; // name of the ship that this goal acts upon
|
||||
int ship_name_index; // index of ship_name in Goal_ship_names[][]
|
||||
int wp_index; // index into waypoints list of waypoints that this ship might fly.
|
||||
int weapon_signature; // signature of weapon this ship might be chasing. Paired with above value to get target.
|
||||
|
||||
// unions for docking stuff.
|
||||
// (AIGF_DOCKER_INDEX_VALID and AIGF_DOCKEE_INDEX_VALID tell us to use indexes; otherwise we use names)
|
||||
@@ -161,7 +146,7 @@ typedef struct ai_goal {
|
||||
|
||||
} ai_goal;
|
||||
|
||||
#define MAX_GOAL_TARGET_NAMES 100
|
||||
#define MAX_GOAL_SHIP_NAMES 100
|
||||
|
||||
#define AIM_CHASE 0
|
||||
#define AIM_EVADE 1
|
||||
@@ -171,25 +156,25 @@ typedef struct ai_goal {
|
||||
#define AIM_GUARD 5 // Guard an object
|
||||
#define AIM_AVOID 6 // Avoid an object
|
||||
#define AIM_WAYPOINTS 7 // Fly waypoints
|
||||
#define AIM_DOCK 8 // Dock with ship.
|
||||
#define AIM_NONE 9 // Uh, do nothing.
|
||||
#define AIM_DOCK 8 // Dock with ship.
|
||||
#define AIM_NONE 9 // Uh, do nothing.
|
||||
#define AIM_BIGSHIP 10 // Like a capital ship, doesn't focus on one ship.
|
||||
#define AIM_PATH 11 // Follow path on ship
|
||||
#define AIM_PATH 11 // Follow path on ship
|
||||
#define AIM_BE_REARMED 12 // Allow self to be rearmed
|
||||
#define AIM_SAFETY 13 // Seek safety at periphery of battle
|
||||
#define AIM_EVADE_WEAPON 14 // Evade a weapon.
|
||||
#define AIM_STRAFE 15 // Attack a big ship by strafing it
|
||||
#define AIM_STRAFE 15 // attack a big ship by strafing it
|
||||
#define AIM_PLAY_DEAD 16 // Play dead. Get it? Don't move, fire, etc.
|
||||
#define AIM_BAY_EMERGE 17 // Emerging from a fighter bay, following path to do so
|
||||
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
|
||||
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
|
||||
#define AIM_BAY_EMERGE 17 // Emerging from a fighter bay, following path to do so
|
||||
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
|
||||
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
|
||||
#define AIM_WARP_OUT 20 // Commence warp out sequence. Point in legal direction. Then call John's code.
|
||||
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
|
||||
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
|
||||
|
||||
#define MAX_AI_BEHAVIORS 22 // Number of AIM_xxxx types
|
||||
#define MAX_AI_BEHAVIORS 22 // Number of AIM_xxxx types
|
||||
|
||||
#define MAX_WAYPOINTS_PER_LIST 20
|
||||
#define MAX_ENEMY_DISTANCE 2500.0f // Maximum distance from which a ship will pursue an enemy.
|
||||
#define MAX_ENEMY_DISTANCE 2500.0f // maximum distance from which a ship will pursue an enemy.
|
||||
|
||||
#define AI_GOAL_NONE -1
|
||||
|
||||
@@ -266,12 +251,13 @@ typedef struct ai_class {
|
||||
#define AIS_CHASE_CIRCLESTRAFE 19 // Attempt a circle-strafe on the target
|
||||
|
||||
// Submodes for docking behavior
|
||||
#define AIS_DOCK_0 20
|
||||
#define AIS_DOCK_1 21
|
||||
#define AIS_DOCK_2 22
|
||||
#define AIS_DOCK_3 23
|
||||
#define AIS_DOCK_4 24 // Only for rearm/repair.
|
||||
#define AIS_DOCK_4A 25 // Only for not rearm/repair. MK, 7/15/97
|
||||
#define AIS_DOCK_0 21
|
||||
#define AIS_DOCK_1 22
|
||||
#define AIS_DOCK_2 23
|
||||
#define AIS_DOCK_3 24
|
||||
//#define AIS_DOCK_3A 25
|
||||
#define AIS_DOCK_4 26 // Only for rearm/repair.
|
||||
#define AIS_DOCK_4A 27 // Only for not rearm/repair. MK, 7/15/97
|
||||
#define AIS_UNDOCK_0 30
|
||||
#define AIS_UNDOCK_1 31
|
||||
#define AIS_UNDOCK_2 32
|
||||
@@ -369,10 +355,11 @@ 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
|
||||
int wp_list; // waypoint list index
|
||||
int 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 wp_dir; // 1 or -1, amount to add to get to next waypoint index.
|
||||
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.
|
||||
@@ -389,7 +376,6 @@ typedef struct ai_info {
|
||||
fix path_next_check_time; // Last time checked to see if would collide with model.
|
||||
int path_goal_dist; // minimum distance to first path point to consider path reached
|
||||
int path_subsystem_next_check; // timestamp to next check if subsystem is still visible
|
||||
vec3d path_depart_orient; //Rotational orientation associated with the path
|
||||
|
||||
int submode;
|
||||
int previous_submode; // previous submode, get it?
|
||||
@@ -475,6 +461,9 @@ typedef struct ai_info {
|
||||
|
||||
float aspect_locked_time; // Time towards acquiring lock for current_target
|
||||
|
||||
// ship_subsys *targeted_subobject; // subsystem to attack
|
||||
// int attack_subsystem_parent; // objnum of the object containing the attack_subsystem
|
||||
|
||||
// Goober5000
|
||||
int support_ship_objnum; // objnum of support ship docking with us, or (if we're a support ship) object we're docking to
|
||||
int support_ship_signature; // signature of the same
|
||||
@@ -520,7 +509,7 @@ typedef struct ai_info {
|
||||
int self_destruct_timestamp; // Time at which to self-destruct, probably due to being disabled.
|
||||
int ok_to_target_timestamp; // Time at which this ship can dynamically target.
|
||||
|
||||
int kamikaze_damage; // some damage value used to produce a shockwave from a kamikaze ship
|
||||
float kamikaze_damage; // some damage value used to produce a shockwave from a kamikaze ship
|
||||
vec3d big_attack_point; // Global point this ship is attacking on a big ship.
|
||||
vec3d big_attack_surface_normal; // Surface normal at ship at big_attack_point;
|
||||
int pick_big_attack_point_timestamp; // timestamp at which to pick a new point to attack on a big ship.
|
||||
@@ -550,17 +539,6 @@ typedef struct ai_info {
|
||||
int ai_override_timestamp; // mark for when to end the current override
|
||||
} ai_info;
|
||||
|
||||
// Goober5000
|
||||
typedef struct {
|
||||
vec3d docker_point;
|
||||
vec3d dockee_point;
|
||||
int dock_mode;
|
||||
int submodel;
|
||||
vec3d submodel_pos;
|
||||
float submodel_r;
|
||||
float submodel_w;
|
||||
} rotating_dockpoint_info;
|
||||
|
||||
#define MAX_AI_INFO MAX_SHIPS
|
||||
|
||||
// SUBSYS_PATH_DIST is used as the distance that a subsystem path should terminate from the actual
|
||||
@@ -573,8 +551,8 @@ typedef struct {
|
||||
#define BURST_DURATION 500 // decay time over which Player->damage_this_burst falls from MAX_BURST_DAMAGE to 0
|
||||
|
||||
extern int Mission_all_attack; // !0 means all teams attack all teams.
|
||||
extern int Total_goal_target_names;
|
||||
extern char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
|
||||
extern int Total_goal_ship_names;
|
||||
extern char Goal_ship_names[MAX_GOAL_SHIP_NAMES][NAME_LENGTH];
|
||||
|
||||
extern void update_ai_info_for_hit(int hitter_obj, int hit_obj);
|
||||
extern void ai_frame_all(void);
|
||||
@@ -590,7 +568,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,17 +594,18 @@ 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_ship_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_start_waypoints(object *objp, int waypoint_list_index, int wp_flags);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum, int method);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = NULL, int sexp_flags = 0);
|
||||
@@ -702,10 +681,6 @@ extern void ai_do_objects_docked_stuff(object *docker, int docker_point, object
|
||||
extern void ai_do_objects_undocked_stuff( object *docker, object *dockee );
|
||||
extern void ai_do_objects_repairing_stuff( object *repaired_obj, object *repair_obj, int how );
|
||||
|
||||
// Goober5000
|
||||
// Move to a position relative to a dock bay using thrusters.
|
||||
extern float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
|
||||
|
||||
extern int find_danger_weapon(object *sobjp, float dtime, float *atime, float dot_threshhold);
|
||||
|
||||
void ai_set_mode_warp_out(object *objp, ai_info *aip);
|
||||
@@ -726,7 +701,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);
|
||||
|
||||
+359
-474
@@ -7,13 +7,11 @@
|
||||
|
||||
|
||||
|
||||
#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 "weapon/weapon.h"
|
||||
#include "localization/localize.h"
|
||||
|
||||
|
||||
// global stuff
|
||||
@@ -48,486 +46,373 @@ void set_flag(ai_profile_t *profile, char *name, int flag, int type)
|
||||
}
|
||||
}
|
||||
|
||||
char *AI_path_types[] = {
|
||||
"normal",
|
||||
"alt1",
|
||||
};
|
||||
|
||||
int Num_ai_path_types = sizeof(AI_path_types)/sizeof(char*);
|
||||
|
||||
int ai_path_type_match(char *p)
|
||||
void parse_ai_profiles_tbl(char *filename)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < Num_ai_path_types; i++)
|
||||
{
|
||||
if(!stricmp(AI_path_types[i], p))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parse_ai_profiles_tbl(const 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 (int i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
profile->glide_attack_percent[i] = 0.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] /= 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 (int i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
profile->circle_strafe_percent[i] = 0.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] /= 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 (int i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
profile->glide_strafe_percent[i] = 0.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] /= 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 (int i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
profile->random_sidethrust_percent[i] = 0.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] /= 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);
|
||||
|
||||
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, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if ( saved_Mp && (saved_Mp == Mp) )
|
||||
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
-31
@@ -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,26 +53,9 @@
|
||||
// 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_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_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)
|
||||
#define AIPF2_PERFORM_LESS_SCREAM_CHECKS (1 << 2)
|
||||
#define AIPF2_ALL_SHIPS_MANAGE_SHIELDS (1 << 3)
|
||||
|
||||
// AI Path types
|
||||
#define AI_PATH_MODE_NORMAL 0
|
||||
#define AI_PATH_MODE_ALT1 1
|
||||
|
||||
#define MAX_AI_PROFILES 5
|
||||
|
||||
typedef struct ai_profile_t {
|
||||
@@ -146,17 +129,6 @@ typedef struct ai_profile_t {
|
||||
// the chance (x/7) that ship is allowed to fire missiles at player ship.
|
||||
int chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS];
|
||||
|
||||
// Player-specific autoaim FOV override
|
||||
float player_autoaim_fov[NUM_SKILL_LEVELS];
|
||||
|
||||
float detail_distance_mult[MAX_DETAIL_LEVEL + 1]; //MAX_DETAIL_LEVEL really needs to be 4
|
||||
|
||||
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;
|
||||
|
||||
|
||||
+110
-150
@@ -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,9 +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;
|
||||
mc.pos = &objp->pos;
|
||||
@@ -370,25 +368,15 @@ 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)
|
||||
return 0;
|
||||
|
||||
pm = model_get( Ship_info[Ships[Pl_objp->instance].ship_info_index].model_num );
|
||||
|
||||
// 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 +420,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) ) {
|
||||
// maybe create a new path
|
||||
if ( subsys_path_num >= 0 ) {
|
||||
Assert(aip->target_objnum >= 0);
|
||||
@@ -478,6 +466,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
|
||||
// for now, only follow the path to the first point
|
||||
if ( aip->path_cur < (aip->path_start+aip->path_length-1) ) {
|
||||
if ( aip->goal_objnum != aip->target_objnum ) {
|
||||
//Int3(); // what is going on here? - Get Alan
|
||||
aip->previous_mode = aip->mode;
|
||||
aip->mode = AIM_NONE;
|
||||
aip->submode = -1;
|
||||
@@ -558,7 +547,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
object *objp;
|
||||
for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
|
||||
if ((objp->type == OBJ_WEAPON) && (iff_x_attacks_y(Ships[Pl_objp->instance].team, Weapons[objp->instance].team)))
|
||||
if (Weapon_info[Weapons[objp->instance].weapon_info_index].subtype == WP_LASER) {
|
||||
if (Weapon_info[objp->instance].subtype == WP_LASER) {
|
||||
vec3d in_vec;
|
||||
float dist;
|
||||
|
||||
@@ -604,15 +593,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 +622,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 +647,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 +707,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -855,12 +821,15 @@ void ai_big_chase()
|
||||
ship_info *sip = &Ship_info[Ships[Pl_objp->instance].ship_info_index];
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
ai_info *aip = &Ai_info[shipp->ai_index];
|
||||
int enemy_ship_type;
|
||||
vec3d predicted_enemy_pos;
|
||||
|
||||
Assert(aip->mode == AIM_CHASE);
|
||||
|
||||
maybe_cheat_fire_synaptic(Pl_objp, aip);
|
||||
|
||||
enemy_ship_type = Ship_info[Ships[En_objp->instance].ship_info_index].flags;
|
||||
|
||||
ai_set_positions(Pl_objp, En_objp, aip, &player_pos, &enemy_pos);
|
||||
|
||||
player_pos = Pl_objp->pos;
|
||||
@@ -887,9 +856,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 +896,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 +913,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();
|
||||
@@ -1206,13 +1161,12 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
|
||||
float weapon_speed;
|
||||
|
||||
// Compute position of gun in absolute space and use that as fire position.
|
||||
if (po->n_guns > 0 && !(The_mission.ai_profile->flags2 & AIPF2_AI_AIMS_FROM_SHIP_CENTER)) {
|
||||
if (po->n_guns > 0) {
|
||||
pnt = po->gun_banks[0].pnt[0];
|
||||
vm_vec_unrotate(&gun_pos, &pnt, &Pl_objp->orient);
|
||||
vm_vec_add2(&gun_pos, &Pl_objp->pos);
|
||||
} else {
|
||||
//Use the convergence offset, if there is one
|
||||
vm_vec_copy_scale(&pnt, &Ship_info[shipp->ship_info_index].convergence_offset, 1.0f);
|
||||
gun_pos = Pl_objp->pos;
|
||||
}
|
||||
weapon_speed = ai_get_weapon_speed(&shipp->weapons);
|
||||
|
||||
@@ -1239,7 +1193,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 +1218,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;
|
||||
@@ -1290,6 +1245,7 @@ void ai_big_strafe_attack()
|
||||
vec3d target_pos;
|
||||
vec3d rand_vec;
|
||||
float target_dist, target_dot, accel, t;
|
||||
object *target_objp;
|
||||
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
|
||||
@@ -1301,8 +1257,11 @@ void ai_big_strafe_attack()
|
||||
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
|
||||
return;
|
||||
|
||||
target_objp = &Objects[aip->target_objnum];
|
||||
|
||||
if (aip->ai_flags & AIF_KAMIKAZE) {
|
||||
if (target_dist < 1200.0f) {
|
||||
//nprintf(("AI", "Kamikaze: %7.3f %7.3f\n", target_dot, target_dist));
|
||||
ai_turn_towards_vector(&target_pos, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
@@ -1338,6 +1297,7 @@ void ai_big_strafe_attack()
|
||||
|
||||
aip->submode = AIS_STRAFE_AVOID;
|
||||
aip->submode_start_time = Missiontime;
|
||||
// nprintf(("Alan","Ship %s entering AIS_STRAFE_AVOID at frame %d\n", Ships[aip->shipnum].ship_name, Framecount));
|
||||
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
@@ -1807,7 +1767,7 @@ void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
|
||||
// Approx 1/4 chance we'll go after the other ship's beam.
|
||||
|
||||
bool attack_turret_on_different_ship = (aip->ai_profile_flags & AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS)
|
||||
&& (Weapon_info[Weapons[weapon_objp->instance].weapon_info_index].wi_flags & WIF_BEAM) && (frand()*100 < 25.0f);
|
||||
&& (Weapon_info[weapon_objp->instance].wi_flags & WIF_BEAM) && (frand()*100 < 25.0f);
|
||||
|
||||
// unless we're making an exception, we should only attack a turret if it sits on the current target
|
||||
if ( !attack_turret_on_different_ship )
|
||||
|
||||
+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();
|
||||
|
||||
+2097
-1992
File diff suppressed because it is too large.
Load diff
+185
-189
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -310,7 +329,7 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
|
||||
mode = remove_goalp->ai_mode;
|
||||
submode = remove_goalp->ai_submode;
|
||||
priority = remove_goalp->priority;
|
||||
name = remove_goalp->target_name;
|
||||
name = remove_goalp->ship_name;
|
||||
|
||||
Assert ( name ); // should not be NULL!!!!
|
||||
|
||||
@@ -326,10 +345,10 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
|
||||
aigp = &(aip->goals[j]);
|
||||
|
||||
// don't need to worry about these types of goals since they can't possibly be a goal we are looking for.
|
||||
if ( (aigp->ai_mode == AI_GOAL_NONE) || !aigp->target_name )
|
||||
if ( (aigp->ai_mode == AI_GOAL_NONE) || !aigp->ship_name )
|
||||
continue;
|
||||
|
||||
if ( (aigp->ai_mode == mode) && (aigp->ai_submode == submode) && (aigp->priority == priority) && !stricmp(name, aigp->target_name) ) {
|
||||
if ( (aigp->ai_mode == mode) && (aigp->ai_submode == submode) && (aigp->priority == priority) && !stricmp(name, aigp->ship_name) ) {
|
||||
ai_remove_ship_goal( aip, j );
|
||||
ai_do_default_behavior( &Objects[Ships[aip->shipnum].objnum] ); // do the default behavior
|
||||
break; // we are all done
|
||||
@@ -340,10 +359,10 @@ void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp )
|
||||
// now remove the goal from the wing
|
||||
for (i = 0; i < MAX_AI_GOALS; i++ ) {
|
||||
aigp = &(wingp->ai_goals[i]);
|
||||
if ( (aigp->ai_mode == AI_GOAL_NONE) || !aigp->target_name )
|
||||
if ( (aigp->ai_mode == AI_GOAL_NONE) || !aigp->ship_name )
|
||||
continue;
|
||||
|
||||
if ( (aigp->ai_mode == mode) && (aigp->ai_submode == submode) && (aigp->priority == priority) && !stricmp(name, aigp->target_name) ) {
|
||||
if ( (aigp->ai_mode == mode) && (aigp->ai_submode == submode) && (aigp->priority == priority) && !stricmp(name, aigp->ship_name) ) {
|
||||
wingp->ai_goals[i].ai_mode = AI_GOAL_NONE;
|
||||
wingp->ai_goals[i].signature = -1;
|
||||
wingp->ai_goals[i].priority = -1;
|
||||
@@ -382,7 +401,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
int mode, ship_index, wingnum;
|
||||
|
||||
// get locals for easer access
|
||||
name = aigp->target_name;
|
||||
name = aigp->ship_name;
|
||||
mode = aigp->ai_mode;
|
||||
|
||||
// these goals cannot be associated to wings, but can to a ship in a wing. So, we should find out
|
||||
@@ -405,17 +424,17 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
continue;
|
||||
|
||||
// goals must operate on something to be purged.
|
||||
if ( purge_goal->target_name == NULL )
|
||||
if ( purge_goal->ship_name == NULL )
|
||||
continue;
|
||||
|
||||
// determine if the purge goal is acting either on the ship or the ship's wing.
|
||||
purge_wing = wing_name_lookup( purge_goal->target_name, 1 );
|
||||
purge_wing = wing_name_lookup( purge_goal->ship_name, 1 );
|
||||
|
||||
// if the target of the purge goal is a ship (purge_wing will be -1), then if the names
|
||||
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
|
||||
// are different.
|
||||
if ( purge_wing == -1 ) {
|
||||
if ( stricmp(purge_goal->target_name, name ) )
|
||||
if ( stricmp(purge_goal->ship_name, name ) )
|
||||
continue;
|
||||
} else if ( purge_wing != wingnum )
|
||||
continue;
|
||||
@@ -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)
|
||||
@@ -541,8 +560,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
int shipnum, docker_index, dockee_index;
|
||||
|
||||
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 );
|
||||
shipnum = ship_name_lookup( aigp->ship_name );
|
||||
docker_index = -1;
|
||||
dockee_index = -1;
|
||||
|
||||
@@ -608,36 +626,27 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
// from the mission goals (i.e. those goals which come from events) in that we don't
|
||||
// use sexpressions for goals from the player...so we enumerate all the parameters
|
||||
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name, ai_goal *aigp )
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, char *shipname, ai_goal *aigp )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
aigp->time = Missiontime;
|
||||
aigp->type = type; // from player for sure -- could be to ship or to wing
|
||||
aigp->ai_mode = mode; // major mode for this goal
|
||||
aigp->type = type; // from player for sure -- could be to ship or to wing
|
||||
aigp->ai_mode = mode; // major mode for this goal
|
||||
aigp->ai_submode = submode; // could mean different things depending on mode
|
||||
|
||||
if ( mode == AI_GOAL_WARP ) {
|
||||
if (submode >= 0) {
|
||||
aigp->wp_list = find_waypoint_list_at_index(submode);
|
||||
Assert(aigp->wp_list != NULL);
|
||||
} else {
|
||||
aigp->wp_list = NULL;
|
||||
}
|
||||
}
|
||||
if ( mode == AI_GOAL_WARP )
|
||||
aigp->wp_index = submode;
|
||||
|
||||
if ( mode == AI_GOAL_CHASE_WEAPON ) {
|
||||
aigp->target_instance = submode; // submode contains the instance of the weapon
|
||||
aigp->target_signature = Objects[Weapons[submode].objnum].signature;
|
||||
} else {
|
||||
aigp->target_instance = -1;
|
||||
aigp->target_signature = -1;
|
||||
aigp->wp_index = submode; // submode contains the instance of the weapon
|
||||
aigp->weapon_signature = Objects[Weapons[submode].objnum].signature;
|
||||
}
|
||||
|
||||
if ( target_name != NULL )
|
||||
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
|
||||
if ( shipname != NULL )
|
||||
aigp->ship_name = ai_get_goal_ship_name( shipname, &aigp->ship_name_index );
|
||||
else
|
||||
aigp->target_name = NULL;
|
||||
aigp->ship_name = NULL;
|
||||
|
||||
// special case certain orders from player so that ships continue to do the right thing
|
||||
|
||||
@@ -702,7 +711,7 @@ int ai_goal_num(ai_goal *goals)
|
||||
}
|
||||
|
||||
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, char *target_name, ai_goal *aigp )
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, char *shipname, ai_goal *aigp )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
@@ -712,17 +721,17 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, ch
|
||||
aigp->ai_submode = submode; // could mean different things depending on mode
|
||||
|
||||
if ( mode == AI_GOAL_WARP )
|
||||
aigp->wp_list = NULL;
|
||||
aigp->wp_index = submode;
|
||||
|
||||
if ( mode == AI_GOAL_CHASE_WEAPON ) {
|
||||
aigp->target_instance = submode; // submode contains the instance of the weapon
|
||||
aigp->target_signature = Objects[Weapons[submode].objnum].signature;
|
||||
aigp->wp_index = submode; // submode contains the instance of the weapon
|
||||
aigp->weapon_signature = Objects[Weapons[submode].objnum].signature;
|
||||
}
|
||||
|
||||
if ( target_name != NULL )
|
||||
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
|
||||
if ( shipname != NULL )
|
||||
aigp->ship_name = ai_get_goal_ship_name( shipname, &aigp->ship_name_index );
|
||||
else
|
||||
aigp->target_name = NULL;
|
||||
aigp->ship_name = NULL;
|
||||
|
||||
aigp->priority = priority;
|
||||
}
|
||||
@@ -815,7 +824,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
|
||||
aigp->signature = Ai_goal_signature++;
|
||||
|
||||
aigp->target_name = NULL;
|
||||
aigp->ship_name = NULL;
|
||||
aigp->time = Missiontime;
|
||||
aigp->type = type;
|
||||
aigp->flags = 0;
|
||||
@@ -830,10 +839,10 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
|
||||
ref_type = Sexp_nodes[CDR(node)].subtype;
|
||||
if (ref_type == SEXP_ATOM_STRING) { // referenced by name
|
||||
// save the waypoint path name -- the list will get resolved when the goal is checked
|
||||
// for achievability.
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
aigp->wp_list = NULL;
|
||||
// save the waypoint path name -- the index will get resolved when the goal is checked
|
||||
// for acheivability.
|
||||
aigp->ship_name = ai_get_goal_ship_name(CTEXT(CDR(node)), &aigp->ship_name_index); // waypoint path name;
|
||||
aigp->wp_index = -1;
|
||||
|
||||
} else
|
||||
Int3();
|
||||
@@ -847,24 +856,24 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
|
||||
case OP_AI_DESTROY_SUBSYS:
|
||||
aigp->ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(node)), &aigp->ship_name_index );
|
||||
// store the name of the subsystem in the docker.name field for now -- this field must get
|
||||
// fixed up when the goal is valid since we need to locate the subsystem on the ship's model
|
||||
aigp->docker.name = ai_get_goal_target_name(CTEXT(CDR(CDR(node))), &dummy);
|
||||
aigp->docker.name = ai_get_goal_ship_name(CTEXT(CDR(CDR(node))), &dummy);
|
||||
aigp->flags |= AIGF_SUBSYS_NEEDS_FIXUP;
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(CDR(node)))) );
|
||||
break;
|
||||
|
||||
case OP_AI_DISABLE_SHIP:
|
||||
aigp->ai_mode = AI_GOAL_DISABLE_SHIP;
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(node)), &aigp->ship_name_index );
|
||||
aigp->ai_submode = -SUBSYSTEM_ENGINE;
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
break;
|
||||
|
||||
case OP_AI_DISARM_SHIP:
|
||||
aigp->ai_mode = AI_GOAL_DISARM_SHIP;
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(node)), &aigp->ship_name_index );
|
||||
aigp->ai_submode = -SUBSYSTEM_TURRET;
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
break;
|
||||
@@ -877,8 +886,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
// the following goal is obsolete, but here for compatibility
|
||||
case OP_AI_WARP:
|
||||
aigp->ai_mode = AI_GOAL_WARP;
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
aigp->wp_list = NULL;
|
||||
aigp->ship_name = ai_get_goal_ship_name(CTEXT(CDR(node)), &aigp->ship_name_index); // waypoint path name;
|
||||
//aigp->wp_index = atoi( CTEXT(CDR(node)) ); // this is the index into the warp points
|
||||
aigp->wp_index = -1;
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
break;
|
||||
|
||||
@@ -887,9 +897,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
|
||||
// Goober5000 - optional undock with something
|
||||
if (CDR(CDR(node)) != -1)
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(CDR(node))), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(CDR(node))), &aigp->ship_name_index );
|
||||
else
|
||||
aigp->target_name = NULL;
|
||||
aigp->ship_name = NULL;
|
||||
|
||||
aigp->ai_mode = AI_GOAL_UNDOCK;
|
||||
aigp->ai_submode = AIS_UNDOCK_0;
|
||||
@@ -897,12 +907,12 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
|
||||
case OP_AI_STAY_STILL:
|
||||
aigp->ai_mode = AI_GOAL_STAY_STILL;
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
aigp->ship_name = ai_get_goal_ship_name(CTEXT(CDR(node)), &aigp->ship_name_index); // waypoint path name;
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
break;
|
||||
|
||||
case OP_AI_DOCK:
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(node)), &aigp->ship_name_index );
|
||||
aigp->docker.name = ai_add_dock_name(CTEXT(CDR(CDR(node))));
|
||||
aigp->dockee.name = ai_add_dock_name(CTEXT(CDR(CDR(CDR(node)))));
|
||||
aigp->flags &= ~AIGF_DOCK_INDEXES_VALID;
|
||||
@@ -927,12 +937,6 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
|
||||
break;
|
||||
|
||||
case OP_AI_FORM_ON_WING:
|
||||
aigp->priority = 99;
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index);
|
||||
aigp->ai_mode = AI_GOAL_FORM_ON_WING;
|
||||
break;
|
||||
|
||||
case OP_AI_CHASE:
|
||||
case OP_AI_GUARD:
|
||||
case OP_AI_GUARD_WING:
|
||||
@@ -941,7 +945,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
case OP_AI_STAY_NEAR_SHIP:
|
||||
case OP_AI_IGNORE:
|
||||
case OP_AI_IGNORE_NEW:
|
||||
aigp->target_name = ai_get_goal_target_name( CTEXT(CDR(node)), &aigp->target_name_index );
|
||||
aigp->ship_name = ai_get_goal_ship_name( CTEXT(CDR(node)), &aigp->ship_name_index );
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
|
||||
if ( op == OP_AI_CHASE ) {
|
||||
@@ -950,12 +954,12 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
// in the case of ai_chase (and ai_guard) we must do a wing_name_lookup on the name
|
||||
// passed here to see if we could be chasing a wing. Hoffoss and I have consolidated
|
||||
// sexpression operators which makes this step necessary
|
||||
if ( wing_name_lookup(aigp->target_name, 1) != -1 )
|
||||
if ( wing_name_lookup(aigp->ship_name, 1) != -1 )
|
||||
aigp->ai_mode = AI_GOAL_CHASE_WING;
|
||||
|
||||
} else if ( op == OP_AI_GUARD ) {
|
||||
aigp->ai_mode = AI_GOAL_GUARD;
|
||||
if ( wing_name_lookup(aigp->target_name, 1) != -1 )
|
||||
if ( wing_name_lookup(aigp->ship_name, 1) != -1 )
|
||||
aigp->ai_mode = AI_GOAL_GUARD_WING;
|
||||
|
||||
} else if ( op == OP_AI_EVADE_SHIP ) {
|
||||
@@ -985,19 +989,9 @@ 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))
|
||||
if (aigp->ship_name != NULL && !strcmp(aigp->ship_name, actor_name))
|
||||
{
|
||||
// based on ai_remove_ship_goal, these seem to be the only statements
|
||||
// necessary to cause this goal to "never have been assigned"
|
||||
@@ -1281,7 +1275,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int doc
|
||||
*/
|
||||
|
||||
case AI_GOAL_UNDOCK:
|
||||
aigp->target_name = name;
|
||||
aigp->ship_name = name;
|
||||
aigp->priority = MAX_GOAL_PRIORITY;
|
||||
aigp->ai_mode = AI_GOAL_UNDOCK;
|
||||
aigp->ai_submode = AIS_UNDOCK_0;
|
||||
@@ -1300,7 +1294,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int doc
|
||||
case AI_GOAL_REARM_REPAIR:
|
||||
aigp->ai_mode = AI_GOAL_REARM_REPAIR;
|
||||
aigp->ai_submode = 0;
|
||||
aigp->target_name = name;
|
||||
aigp->ship_name = name;
|
||||
aigp->priority = PLAYER_PRIORITY_MIN-1; // make the priority always less than what the player's is
|
||||
aigp->flags &= ~AIGF_GOAL_OVERRIDE; // don't override this goal. rearm repair requests should happen in order
|
||||
ai_goal_fixup_dockpoints( aip, aigp );
|
||||
@@ -1365,6 +1359,7 @@ void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
|
||||
int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
{
|
||||
int status;
|
||||
char *ai_shipname;
|
||||
int return_val;
|
||||
object *objp;
|
||||
ai_info *aip;
|
||||
@@ -1373,6 +1368,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
|
||||
objp = &Objects[objnum];
|
||||
Assert( objp->instance != -1 );
|
||||
ai_shipname = Ships[objp->instance].ship_name;
|
||||
aip = &Ai_info[Ships[objp->instance].ai_index];
|
||||
|
||||
// these orders are always achievable.
|
||||
@@ -1390,17 +1386,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1408,7 +1400,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// if the wing target is valid then be sure to set the override bit so that it always
|
||||
// gets executed next
|
||||
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
|
||||
if (sindex < 0)
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
@@ -1417,14 +1409,20 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
}
|
||||
|
||||
// check to see if we have a valid list. If not, then try to set one up. If that
|
||||
// check to see if we have a valid index. If not, then try to set one up. If that
|
||||
// fails, then we must pitch this order
|
||||
if ( (aigp->ai_mode == AI_GOAL_WAYPOINTS_ONCE) || (aigp->ai_mode == AI_GOAL_WAYPOINTS) ) {
|
||||
if ( aigp->wp_list == NULL ) {
|
||||
aigp->wp_list = find_matching_waypoint_list(aigp->target_name);
|
||||
if ( aigp->wp_index == -1 ) {
|
||||
int i;
|
||||
|
||||
if ( aigp->wp_list == NULL ) {
|
||||
Warning(LOCATION, "Unknown waypoint list %s - not found in mission file. Killing ai goal", aigp->target_name );
|
||||
for (i = 0; i < Num_waypoint_lists; i++) {
|
||||
if (!stricmp(aigp->ship_name, Waypoint_lists[i].name)) {
|
||||
aigp->wp_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i == Num_waypoint_lists ) {
|
||||
Warning(LOCATION, "Unknown waypoint %s. not found in mission file. Killing ai goal", aigp->ship_name );
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
}
|
||||
}
|
||||
@@ -1439,6 +1437,8 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
{
|
||||
case AI_GOAL_DOCK:
|
||||
case AI_GOAL_UNDOCK:
|
||||
//status = mission_log_get_time( LOG_SHIP_DOCK, ai_shipname, aigp->ship_name, NULL );
|
||||
//status = mission_log_get_time( LOG_SHIP_UNDOCK, ai_shipname, aigp->ship_name, NULL );
|
||||
//MWA 3/20/97 -- cannot short circuit a dock or undock goal already succeeded -- we must
|
||||
// rely on the goal removal code to just remove this goal. This is because docking/undock
|
||||
// can happen > 1 time per mission per pair of ships. The above checks will find only
|
||||
@@ -1452,7 +1452,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
|
||||
// shipnum could be -1 depending on if the ship hasn't arrived or died. only look for subsystem
|
||||
// destroyed when shipnum is valid
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
// or we haven't found a valid subsystem index yet
|
||||
@@ -1466,22 +1466,17 @@ 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->ship_name, ssp->system_info->subobj_name, NULL );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AI_GOAL_DISABLE_SHIP:
|
||||
status = mission_log_get_time( LOG_SHIP_DISABLED, aigp->target_name, NULL, NULL );
|
||||
status = mission_log_get_time( LOG_SHIP_DISABLED, aigp->ship_name, NULL, NULL );
|
||||
break;
|
||||
|
||||
case AI_GOAL_DISARM_SHIP:
|
||||
status = mission_log_get_time( LOG_SHIP_DISARMED, aigp->target_name, NULL, NULL );
|
||||
status = mission_log_get_time( LOG_SHIP_DISARMED, aigp->ship_name, NULL, NULL );
|
||||
break;
|
||||
|
||||
// to guard or ignore a ship, the goal cannot continue if the ship being guarded is either destroyed
|
||||
@@ -1498,18 +1493,14 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// MWA -- 4/22/98. Check for the ship actually being in the mission before
|
||||
// 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 ) {
|
||||
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->target_name, NULL, NULL);
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
if ( sindex == -1 ) {
|
||||
status = mission_log_get_time( LOG_SHIP_DEPARTED, aigp->ship_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);
|
||||
}
|
||||
status = mission_log_get_time( LOG_SHIP_DESTROYED, aigp->ship_name, NULL, NULL);
|
||||
if ( status )
|
||||
return_val = AI_GOAL_NOT_ACHIEVABLE;
|
||||
}
|
||||
|
||||
if ( status )
|
||||
return_val = AI_GOAL_NOT_ACHIEVABLE;
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
@@ -1520,9 +1511,9 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
case AI_GOAL_CHASE_WING:
|
||||
case AI_GOAL_GUARD_WING:
|
||||
{
|
||||
status = mission_log_get_time( LOG_WING_DEPARTED, aigp->target_name, NULL, NULL );
|
||||
status = mission_log_get_time( LOG_WING_DEPARTED, aigp->ship_name, NULL, NULL );
|
||||
if ( !status ) {
|
||||
status = mission_log_get_time( LOG_WING_DESTROYED, aigp->target_name, NULL, NULL);
|
||||
status = mission_log_get_time( LOG_WING_DESTROYED, aigp->ship_name, NULL, NULL);
|
||||
if ( status )
|
||||
return_val = AI_GOAL_NOT_ACHIEVABLE;
|
||||
}
|
||||
@@ -1535,13 +1526,13 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
{
|
||||
// for chase weapon, we simply need to look at the weapon instance that we are trying to
|
||||
// attack and see if the object still exists, and has the same signature that we expect.
|
||||
Assert( aigp->target_instance >= 0 );
|
||||
Assert( aigp->wp_index >= 0 );
|
||||
|
||||
if ( Weapons[aigp->target_instance].objnum == -1 )
|
||||
if ( Weapons[aigp->wp_index].objnum == -1 )
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
|
||||
// if the signatures don't match, then goal isn't achievable.
|
||||
if ( Objects[Weapons[aigp->target_instance].objnum].signature != aigp->target_signature )
|
||||
if ( Objects[Weapons[aigp->wp_index].objnum].signature != aigp->weapon_signature )
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
|
||||
// otherwise, we should be good to go
|
||||
@@ -1566,7 +1557,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// the if statement.
|
||||
if ( (aigp->ai_mode == AI_GOAL_CHASE_WING) || (aigp->ai_mode == AI_GOAL_GUARD_WING) )
|
||||
{
|
||||
sindex = wing_name_lookup( aigp->target_name );
|
||||
sindex = wing_name_lookup( aigp->ship_name );
|
||||
|
||||
if (sindex < 0)
|
||||
return AI_GOAL_NOT_KNOWN;
|
||||
@@ -1582,24 +1573,24 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
// Goober5000 - undocking from an unspecified object is always achievable;
|
||||
// undocking from a specified object is handled below
|
||||
else if ( (aigp->ai_mode == AI_GOAL_UNDOCK) && (aigp->target_name == NULL) )
|
||||
else if ( (aigp->ai_mode == AI_GOAL_UNDOCK) && (aigp->ship_name == NULL) )
|
||||
{
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// goal ship is currently in mission
|
||||
if ( ship_name_lookup( aigp->target_name ) != -1 )
|
||||
if ( ship_name_lookup( aigp->ship_name ) != -1 )
|
||||
{
|
||||
status = SHIP_STATUS_ARRIVED;
|
||||
}
|
||||
// goal ship is still on the arrival list
|
||||
else if ( mission_parse_get_arrival_ship(aigp->target_name) )
|
||||
else if ( mission_parse_get_arrival_ship(aigp->ship_name) )
|
||||
{
|
||||
status = SHIP_STATUS_NOT_ARRIVED;
|
||||
}
|
||||
// goal ship has left the area
|
||||
else if ( ship_find_exited_ship_by_name(aigp->target_name) != -1 )
|
||||
else if ( ship_find_exited_ship_by_name(aigp->ship_name) != -1 )
|
||||
{
|
||||
status = SHIP_STATUS_GONE;
|
||||
}
|
||||
@@ -1614,7 +1605,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP))
|
||||
{
|
||||
// if the ship has no turrets, we can't disarm it!
|
||||
if (Ships[ship_name_lookup(aigp->target_name)].subsys_info[SUBSYSTEM_TURRET].type_count == 0)
|
||||
if (Ships[ship_name_lookup(aigp->ship_name)].subsys_info[SUBSYSTEM_TURRET].num == 0)
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
}
|
||||
|
||||
@@ -1645,7 +1636,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
|
||||
if (!(aigp->flags & AIGF_DOCKEE_INDEX_VALID)) {
|
||||
sindex = ship_name_lookup(aigp->target_name);
|
||||
sindex = ship_name_lookup(aigp->ship_name);
|
||||
if ( sindex != -1 ) {
|
||||
modelnum = Ship_info[Ships[sindex].ship_info_index].model_num;
|
||||
index = model_find_dock_name_index(modelnum, aigp->dockee.name);
|
||||
@@ -1665,7 +1656,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
return AI_GOAL_NOT_KNOWN;
|
||||
|
||||
// we must also determine if we're prevented from docking for any reason
|
||||
sindex = ship_name_lookup(aigp->target_name);
|
||||
sindex = ship_name_lookup(aigp->ship_name);
|
||||
Assert( sindex >= 0 );
|
||||
object *goal_objp = &Objects[Ships[sindex].objnum];
|
||||
|
||||
@@ -1717,7 +1708,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
|
||||
{
|
||||
// only put it on hold if it's someone other than the guy we're undocking from right now!!
|
||||
if (aip->goal_objnum != Ships[ship_name_lookup(aigp->target_name)].objnum)
|
||||
if (aip->goal_objnum != Ships[ship_name_lookup(aigp->ship_name)].objnum)
|
||||
return AI_GOAL_NOT_KNOWN;
|
||||
}
|
||||
|
||||
@@ -1726,7 +1717,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
|
||||
// the ship's subsystem list
|
||||
if ( aigp->flags & AIGF_SUBSYS_NEEDS_FIXUP ) {
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
|
||||
if ( sindex != -1 ) {
|
||||
aigp->ai_submode = ship_get_subsys_index( &Ships[sindex], aigp->docker.name );
|
||||
@@ -1740,7 +1731,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
object *ignored;
|
||||
|
||||
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
Assert( sindex != -1 ); // should be true because of above status
|
||||
ignored = &Objects[Ships[sindex].objnum];
|
||||
|
||||
@@ -1794,7 +1785,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if ( status == SHIP_STATUS_GONE )
|
||||
return AI_GOAL_NOT_ACHIEVABLE;
|
||||
|
||||
sindex = ship_name_lookup( aigp->target_name );
|
||||
sindex = ship_name_lookup( aigp->ship_name );
|
||||
|
||||
if ( sindex < 0 ) {
|
||||
Int3();
|
||||
@@ -1820,6 +1811,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
|
||||
// test code!!!
|
||||
if ( aip->goal_objnum == -1 ) {
|
||||
// -- MK, 11/9/97 -- I was always hitting this: Int3();
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
}
|
||||
|
||||
@@ -1888,8 +1880,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 +1998,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) {
|
||||
@@ -2052,8 +2045,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
switch ( current_goal->ai_mode ) {
|
||||
|
||||
case AI_GOAL_CHASE:
|
||||
if ( current_goal->target_name ) {
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
if ( current_goal->ship_name ) {
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
} else
|
||||
@@ -2065,14 +2058,13 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
case AI_GOAL_CHASE_WEAPON:
|
||||
Assert( Weapons[current_goal->target_instance].objnum >= 0 );
|
||||
other_obj = &Objects[Weapons[current_goal->target_instance].objnum];
|
||||
Assert( other_obj->signature == current_goal->target_signature );
|
||||
Assert( Weapons[current_goal->wp_index].objnum != -1 );
|
||||
other_obj = &Objects[Weapons[current_goal->wp_index].objnum];
|
||||
ai_attack_object( objp, other_obj, NULL );
|
||||
break;
|
||||
|
||||
case AI_GOAL_GUARD:
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
// shipnum and other_obj are the shipnumber and object pointer of the object that you should
|
||||
@@ -2087,7 +2079,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
case AI_GOAL_GUARD_WING:
|
||||
wingnum = wing_name_lookup( current_goal->target_name );
|
||||
wingnum = wing_name_lookup( current_goal->ship_name );
|
||||
Assert (wingnum != -1 ); // shouldn't get here if this is false!!!!
|
||||
ai_set_guard_wing(objp, wingnum);
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -2099,18 +2091,18 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
|
||||
if ( current_goal->ai_mode == AI_GOAL_WAYPOINTS)
|
||||
flags |= WPF_REPEAT;
|
||||
ai_start_waypoints(objp, current_goal->wp_list, flags);
|
||||
ai_start_waypoints(objp, current_goal->wp_index, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
case AI_GOAL_FLY_TO_SHIP:
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
|
||||
ai_start_fly_to_ship(objp, shipnum);
|
||||
break;
|
||||
|
||||
case AI_GOAL_DOCK: {
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
|
||||
@@ -2127,9 +2119,9 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
// goal cannot continue. Spit out a warning and remove the goal.
|
||||
|
||||
// Goober5000 - do we have a specific ship to undock from?
|
||||
if ( current_goal->target_name != NULL )
|
||||
if ( current_goal->ship_name != NULL )
|
||||
{
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
|
||||
// hmm, perhaps he was destroyed
|
||||
if (shipnum == -1)
|
||||
@@ -2152,7 +2144,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
other_obj = dock_get_first_docked_object( objp );
|
||||
|
||||
// and add the ship name so it displays on the HUD
|
||||
current_goal->target_name = Ships[other_obj->instance].ship_name;
|
||||
current_goal->ship_name = Ships[other_obj->instance].ship_name;
|
||||
}
|
||||
// hmm, nobody exists that we can undock from
|
||||
else
|
||||
@@ -2162,6 +2154,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
}
|
||||
|
||||
if ( other_obj == NULL ) {
|
||||
//Int3();
|
||||
// assume that the guy he was docked with doesn't exist anymore. (i.e. a cargo containuer
|
||||
// can get destroyed while docked with a freighter.) We should just remove this goal and
|
||||
// let this ship pick up it's next goal.
|
||||
@@ -2190,7 +2183,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
case AI_GOAL_DESTROY_SUBSYSTEM:
|
||||
case AI_GOAL_DISABLE_SHIP:
|
||||
case AI_GOAL_DISARM_SHIP: {
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert( shipnum >= 0 );
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
ai_attack_object( objp, other_obj, NULL);
|
||||
@@ -2209,7 +2202,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
}
|
||||
|
||||
case AI_GOAL_CHASE_WING:
|
||||
wingnum = wing_name_lookup( current_goal->target_name );
|
||||
wingnum = wing_name_lookup( current_goal->ship_name );
|
||||
Assert( wingnum >= 0 );
|
||||
ai_attack_wing(objp, wingnum);
|
||||
break;
|
||||
@@ -2219,12 +2212,15 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
case AI_GOAL_WARP: {
|
||||
mission_do_departure( objp, true );
|
||||
int index;
|
||||
|
||||
index = current_goal->wp_index;
|
||||
mission_do_departure( objp );
|
||||
break;
|
||||
}
|
||||
|
||||
case AI_GOAL_EVADE_SHIP:
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert( shipnum >= 0 );
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
ai_evade_object( objp, other_obj);
|
||||
@@ -2253,7 +2249,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
// on wing AI code
|
||||
// clearing out goals is okay here since we are now what mode to set this AI object to.
|
||||
ai_clear_ship_goals( aip );
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert( shipnum >= 0 );
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
ai_form_on_wing( objp, other_obj );
|
||||
@@ -2262,7 +2258,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
// labels for support ship commands
|
||||
|
||||
case AI_GOAL_STAY_NEAR_SHIP: {
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert( shipnum >= 0 );
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
// todo MK: hook to keep support ship near other_obj -- other_obj could be the player object!!!
|
||||
@@ -2279,7 +2275,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
case AI_GOAL_REARM_REPAIR:
|
||||
shipnum = ship_name_lookup( current_goal->target_name );
|
||||
shipnum = ship_name_lookup( current_goal->ship_name );
|
||||
Assert( shipnum >= 0 );
|
||||
other_obj = &Objects[Ships[shipnum].objnum];
|
||||
ai_rearm_repair( objp, current_goal->docker.index, other_obj, current_goal->dockee.index );
|
||||
@@ -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;
|
||||
|
||||
@@ -2350,16 +2346,16 @@ void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, c
|
||||
}
|
||||
|
||||
if (flag) // is this a valid goal to parse for this conversion?
|
||||
if (!stricmp(goals[i].target_name, old_name)) {
|
||||
if (!stricmp(goals[i].ship_name, old_name)) {
|
||||
if (*new_name == '<') // target was just deleted..
|
||||
goals[i].ai_mode = AI_GOAL_NONE;
|
||||
else
|
||||
goals[i].target_name = ai_get_goal_target_name(new_name, &dummy);
|
||||
goals[i].ship_name = ai_get_goal_ship_name(new_name, &dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -2416,7 +2412,7 @@ int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name)
|
||||
|
||||
if (flag) // is this a valid goal to parse for this conversion?
|
||||
{
|
||||
if (!stricmp(goals[i].target_name, name))
|
||||
if (!stricmp(goals[i].ship_name, name))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2424,12 +2420,12 @@ 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;
|
||||
|
||||
Assert(strlen(str) <= NAME_LENGTH - 1);
|
||||
Assert(strlen(str) < NAME_LENGTH - 1);
|
||||
for (i=0; i<Num_ai_dock_names; i++)
|
||||
if (!stricmp(Ai_dock_names[i], str))
|
||||
return Ai_dock_names[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
|
||||
+198
-859
File diff suppressed because it is too large.
Load diff
+189
-124
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -31,17 +31,16 @@ anim_instance anim_render_list;
|
||||
#define MAX_ANIM_INSTANCES 25
|
||||
anim_instance anim_render_instance[MAX_ANIM_INSTANCES];
|
||||
|
||||
int Anim_paused; /// Global variable to pause the playing back of anims
|
||||
int Anim_paused; // global variable to pause the playing back of anims
|
||||
int Anim_inited = FALSE;
|
||||
|
||||
fix t1,t2;
|
||||
|
||||
int Anim_ignore_frametime=0; // flag used to ignore frametime... useful when need to avoid saturated frametimes
|
||||
|
||||
/**
|
||||
* @brief Initialise animation
|
||||
* @details Queue all the ::anim_render_instance[] elements onto the ::anim_free_list
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// anim_init() will queue all the anim_render_instance[] elements onto the anim_free_list
|
||||
//
|
||||
void anim_init()
|
||||
{
|
||||
int i;
|
||||
@@ -61,9 +60,9 @@ void anim_init()
|
||||
Anim_inited = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display the frames for the currently playing anims
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// anim_render_all() will display the frames for the currently playing anims
|
||||
//
|
||||
void anim_render_all(int screen_id, float frametime)
|
||||
{
|
||||
anim_instance* A;
|
||||
@@ -86,10 +85,10 @@ void anim_render_all(int screen_id, float frametime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display the frames for the passed animation
|
||||
* @details It will ignore animations which do not have the same id as the passed screen_id
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// anim_render_one() will display the frames for the passed animation, it will ignore animations which
|
||||
// do not have the same id as the passed screen_id
|
||||
//
|
||||
void anim_render_one(int screen_id, anim_instance *ani, float frametime)
|
||||
{
|
||||
// make sure this guy's screen id matches the passed one
|
||||
@@ -110,17 +109,14 @@ void anim_render_one(int screen_id, anim_instance *ani, float frametime)
|
||||
|
||||
MONITOR(NumANIPlayed)
|
||||
|
||||
/**
|
||||
* @brief Setup an anim_play_struct for passing into ::anim_play().
|
||||
* @details Will fill in default values, which you can then change before calling ::anim_play().
|
||||
*/
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int base_w, int base_h)
|
||||
// Setup an anim_play_struct for passing into anim_play(). Will fill in default values, which you
|
||||
// can then change before calling anim_play().
|
||||
//
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y)
|
||||
{
|
||||
aps->anim_info = a_info;
|
||||
aps->x = x;
|
||||
aps->y = y;
|
||||
aps->base_w = base_w;
|
||||
aps->base_h = base_h;
|
||||
aps->start_at = 0;
|
||||
aps->stop_at = a_info->total_frames - 1;
|
||||
aps->screen_id = 0;
|
||||
@@ -133,21 +129,49 @@ void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int base_
|
||||
aps->ping_pong = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Will add an anim instance to the anim_render_list.
|
||||
* This will cause the anim to be played at the x,y position specified in the parameter list.
|
||||
*
|
||||
* @param aps Compressed animation that we should make an instance from
|
||||
* @return If success pointer to instance, NULL if anim anim could not be played
|
||||
*/
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// anim_play() will add an anim instance to the anim_render_list. This will cause the
|
||||
// anim to be played at the x,y position specified in the parameter list.
|
||||
//
|
||||
// input:
|
||||
//
|
||||
// anim_info => the compressed animation that we should make an instance from
|
||||
// x => x position of animation to play at (top left corner)
|
||||
// y => y position of animation to play at ( top left corner)
|
||||
// start_at => frame number to start at (note: numbering is from 0->num_frames-1)
|
||||
// stop_at => frame number to stop at (note: numbering is from 0->num_frames-1)
|
||||
// screen_id => OPTIONAL (default value 0): screen signature so animation only plays when
|
||||
// anim_render_all() called with that same signature
|
||||
// world_pos => OPTIONAL (default value NULL): only give a world pos when you want to
|
||||
// play the animation at a 3D location. You must specify radius when
|
||||
// this is non-null.
|
||||
// radius => OPTIONAL (default value 0): only needed when the animation is playing
|
||||
// as a 3D animation (this is only when world_pos in not NULL).
|
||||
// fi => OPTIONAL (default value 0): framerate indepentdent flag, when set TRUE
|
||||
// the animation will skip frames if necessary to maintain the fps value
|
||||
// associated with the animation
|
||||
// color => OPTIONAL (default value NULL) address of an alpha color struct. Only
|
||||
// required when the animation should be drawn with an alpha color.
|
||||
// skip_frames => OPTIONAL (default value 1) should anim skip frames when doing framerate
|
||||
// independent playback
|
||||
// looped => OPTIONAL (default value 0) should anim play looped (ie forever)
|
||||
//
|
||||
// returns:
|
||||
//
|
||||
// pointer to instance => success
|
||||
// NULL => if anim anim could not be played
|
||||
//
|
||||
anim_instance *anim_play(anim_play_struct *aps)
|
||||
{
|
||||
Assert( aps->anim_info != NULL );
|
||||
Assert( aps->start_at >= 0 );
|
||||
Assert( aps->stop_at < aps->anim_info->total_frames );
|
||||
// Assert( aps->stop_at >= aps->start_at );
|
||||
Assert( !(aps->looped && aps->ping_pong) ); // shouldn't have these both set at once
|
||||
|
||||
MONITOR_INC(NumANIPlayed, 1);
|
||||
|
||||
// if (aps->ping_pong && !(aps->anim_info->flags & ANF_ALL_KEYFRAMES));
|
||||
|
||||
anim_instance *instance;
|
||||
|
||||
@@ -195,14 +219,6 @@ anim_instance *anim_play(anim_play_struct *aps)
|
||||
instance->xlate_pal = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
instance->base_w = aps->base_w;
|
||||
instance->base_h = aps->base_h;
|
||||
}
|
||||
|
||||
// determining the start_at frame is more complicated, since it must be a key-frame.
|
||||
// Futhermore, need to subtract 1 from key-frame number, since frame number is always
|
||||
// incremented the first time anim_show_next_frame() is called
|
||||
@@ -227,6 +243,16 @@ anim_instance *anim_play(anim_play_struct *aps)
|
||||
|
||||
idx++;
|
||||
}
|
||||
/*while (keyp) {
|
||||
if (( (keyp->frame_num-1) <= frame_num) && ( (keyp->frame_num-1) > key)) { // find closest key
|
||||
key = keyp->frame_num-1;
|
||||
offset = keyp->offset;
|
||||
if ( key == frame_num )
|
||||
break;
|
||||
}
|
||||
|
||||
keyp = keyp->next;
|
||||
}*/
|
||||
|
||||
if (key > instance->frame_num) { // best key is closer than current position
|
||||
instance->frame_num = key;
|
||||
@@ -244,17 +270,20 @@ anim_instance *anim_play(anim_play_struct *aps)
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is called to blit the next frame of an anim instance to the screen.
|
||||
* This is normally called by the anim_render_all() function.
|
||||
*
|
||||
* @param instance Pointer to animation instance
|
||||
* @param frametime Time elapsed since last call, in seconds
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_show_next_frame()
|
||||
//
|
||||
// This function is called to blit the next frame of an anim instance to the
|
||||
// screen. This is normally called by the anim_render_all() function.
|
||||
//
|
||||
// input: instance => pointer to animation instance
|
||||
// frametime => time elapsed since last call, in seconds
|
||||
//
|
||||
|
||||
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;
|
||||
int bitmap_id, bitmap_flags=0, new_frame_num, frame_diff=0, i, n_frames=0,frame_save;
|
||||
float percent_through, decompress_time, render_time, time;
|
||||
vertex image_vertex;
|
||||
int aabitmap = 0;
|
||||
int bpp = 16;
|
||||
@@ -336,6 +365,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
instance->time_elapsed = 0.0f;
|
||||
} else if(instance->ping_pong) { // pingponged animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
// instance->time_elapsed = 0.0f;
|
||||
anim_reverse_direction(instance);
|
||||
} else { // one-shot animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
@@ -350,6 +380,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
instance->time_elapsed = 0.0f;
|
||||
} else if(instance->ping_pong) { // pingponged animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
// instance->time_elapsed = 0.0f;
|
||||
anim_reverse_direction(instance);
|
||||
} else { // one-shot animations
|
||||
instance->frame_num = instance->stop_at+1;
|
||||
@@ -373,6 +404,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
}
|
||||
}
|
||||
Assert(frame_diff >= 0);
|
||||
// nprintf(("Alan","FRAME DIFF: %d\n",frame_diff));
|
||||
Assert( instance->frame_num >= 0 && instance->frame_num < instance->parent->total_frames );
|
||||
|
||||
// if the anim is paused, ignore all the above changes and still display this frame
|
||||
@@ -383,6 +415,7 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
}
|
||||
|
||||
if (instance->parent->flags & ANF_XPARENT){
|
||||
// bitmap_flags = BMP_XPARENT;
|
||||
bitmap_flags = 0;
|
||||
}
|
||||
bpp = 16;
|
||||
@@ -461,6 +494,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 +505,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,21 +521,13 @@ 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);
|
||||
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_clip();
|
||||
}
|
||||
else {
|
||||
g3_rotate_vertex(&image_vertex,instance->world_pos);
|
||||
@@ -508,17 +535,23 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
g3_draw_bitmap(&image_vertex, 0, instance->radius*1.5f, TMAP_FLAG_TEXTURED | TMAP_HTL_2D);
|
||||
}
|
||||
|
||||
//bm_release(bitmap_id);
|
||||
instance->last_bitmap = bitmap_id;
|
||||
}
|
||||
|
||||
t2 = timer_get_fixed_seconds();
|
||||
render_time = f2fl(t2-t1);
|
||||
|
||||
// nprintf(("Alan","DECOMPRESS: %.3fms RENDER: %.3fms\n", decompress_time*1000, render_time*1000));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop an anim instance that is on the anim_render_list from playing
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_stop_playing()
|
||||
//
|
||||
// Stop an anim instance that is on the anim_render_list from playing
|
||||
//
|
||||
int anim_stop_playing(anim_instance* instance)
|
||||
{
|
||||
Assert(instance != NULL);
|
||||
@@ -529,12 +562,14 @@ int anim_stop_playing(anim_instance* instance)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free a particular animation instance that is on the anim_render_list.
|
||||
* Do not call this function to free an animation instance in general (use
|
||||
* free_anim_instance() for that), only when you want to free an instance
|
||||
* that is on the anim_render_list
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_release_render_instance()
|
||||
//
|
||||
// Free a particular animation instance that is on the anim_render_list. Do
|
||||
// not call this function to free an animation instance in general (use
|
||||
// free_anim_instance() for that), only when you want to free an instance
|
||||
// that is on the anim_render_list
|
||||
//
|
||||
void anim_release_render_instance(anim_instance* instance)
|
||||
{
|
||||
Assert( instance != NULL );
|
||||
@@ -557,13 +592,16 @@ void anim_release_render_instance(anim_instance* instance)
|
||||
list_append( &anim_free_list, instance );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free all anim instances that are on the anim_render_list.
|
||||
*
|
||||
* @param screen_id Optional parameter that lets you only free a subset of the anim instances.
|
||||
* A screen_id of 0 is the default value, and this is used for animations that always play when
|
||||
* they are placed on the aim_render_list.
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_release_all_instances()
|
||||
//
|
||||
// Free all anim instances that are on the anim_render_list.
|
||||
//
|
||||
// input: screen_id => optional parameter that lets you only free a subset
|
||||
// of the anim instances. A screen_id of 0 is the default
|
||||
// value, and this is used for animations that always play
|
||||
// when they are placed on the aim_render_list.
|
||||
//
|
||||
void anim_release_all_instances(int screen_id)
|
||||
{
|
||||
anim_instance* A;
|
||||
@@ -587,18 +625,18 @@ void anim_release_all_instances(int screen_id)
|
||||
//
|
||||
// Read the header of a .ani file. Below is the format of a .ani header
|
||||
//
|
||||
// #bytes | description
|
||||
// #bytes | description
|
||||
// 2 | obsolete, kept for compatibility with old versions
|
||||
// 2 | version number
|
||||
// 2 | fps
|
||||
// 1 | transparent red value
|
||||
// 1 | transparent green value
|
||||
// 1 | transparent green value
|
||||
// 1 | transparent blue value
|
||||
// 2 | width
|
||||
// 2 | height
|
||||
// 2 | number of frames
|
||||
// 1 | packer code
|
||||
// 763 | palette
|
||||
// 763 | palette
|
||||
// 2 | number of key frames
|
||||
// 2 | key frame number } repeats
|
||||
// 4 | key frame offset } repeats
|
||||
@@ -608,7 +646,7 @@ void anim_read_header(anim *ptr, CFILE *fp)
|
||||
{
|
||||
ptr->width = cfread_short(fp);
|
||||
// If first 2 bytes are zero, this means we are using a new format, which includes
|
||||
// a version, and fps values. This is only done since a version number was not included
|
||||
// a version, and fps values. This is only done since a version number was not included
|
||||
// in the original header.
|
||||
|
||||
// default
|
||||
@@ -673,17 +711,20 @@ void anim_read_header(anim *ptr, CFILE *fp)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load an animation. This stores the compressed data, which instances of the animation can reference.
|
||||
* Must be free'ed later with anim_free().
|
||||
*
|
||||
* @param real_filename Filename of animation
|
||||
* @param cf_dir_type
|
||||
* @param file_mapped Whether to use memory-mapped file or not.
|
||||
*
|
||||
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
|
||||
* @return Pointer to anim that is loaded if sucess, NULL if failure.
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_load()
|
||||
//
|
||||
// Load an animation. This stores the compressed data, which instances
|
||||
// of the animation can reference. Must be free'ed later with anim_free()
|
||||
//
|
||||
// input: name => filename of animation
|
||||
// file_mapped => boolean, whether to use memory-mapped file or not.
|
||||
// Memory-mapped files will page in the animation from disk
|
||||
// as it is needed, but performance is not as good
|
||||
//
|
||||
// returns: pointer to anim that is loaded => sucess
|
||||
// NULL => failure
|
||||
//
|
||||
anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped)
|
||||
{
|
||||
anim *ptr;
|
||||
@@ -691,7 +732,7 @@ anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped)
|
||||
int count,idx;
|
||||
char name[_MAX_PATH];
|
||||
|
||||
Assert( real_filename != NULL );
|
||||
Assert ( real_filename != NULL );
|
||||
|
||||
strcpy_s( name, real_filename );
|
||||
char *p = strchr( name, '.' );
|
||||
@@ -742,10 +783,22 @@ anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped)
|
||||
ptr->keys[idx].frame_num = 0;
|
||||
cfread(&ptr->keys[idx].frame_num, 2, 1, fp);
|
||||
cfread(&ptr->keys[idx].offset, 4, 1, fp);
|
||||
ptr->keys[idx].frame_num = INTEL_INT( ptr->keys[idx].frame_num ); //-V570
|
||||
ptr->keys[idx].offset = INTEL_INT( ptr->keys[idx].offset ); //-V570
|
||||
ptr->keys[idx].frame_num = INTEL_INT( ptr->keys[idx].frame_num );
|
||||
ptr->keys[idx].offset = INTEL_INT( ptr->keys[idx].offset );
|
||||
}
|
||||
|
||||
/*prev_keyp = &ptr->keys;
|
||||
count = ptr->num_keys;
|
||||
while (count--) {
|
||||
keyp = (key_frame *) vm_malloc(sizeof(key_frame));
|
||||
keyp->next = *prev_keyp;
|
||||
*prev_keyp = keyp;
|
||||
prev_keyp = &keyp->next;
|
||||
|
||||
keyp->frame_num = 0;
|
||||
cfread(&keyp->frame_num, 2, 1, fp);
|
||||
cfread(&keyp->offset, 4, 1, fp);
|
||||
}*/
|
||||
cfread(&count, 4, 1, fp); // size of compressed data
|
||||
count = INTEL_INT( count );
|
||||
|
||||
@@ -806,10 +859,12 @@ anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free an animation that was loaded with anim_load().
|
||||
* @details All instances referencing this animation must be free'ed or get an assert.
|
||||
*/
|
||||
// ---------------------------------------------------
|
||||
// anim_free()
|
||||
//
|
||||
// Free an animation that was loaded with anim_load(). All instances
|
||||
// referencing this animation must be free'ed or get an assert.
|
||||
//
|
||||
int anim_free(anim *ptr)
|
||||
{
|
||||
Assert ( ptr != NULL );
|
||||
@@ -841,14 +896,14 @@ int anim_free(anim *ptr)
|
||||
|
||||
if ( ptr->flags & (ANF_MEM_MAPPED|ANF_STREAMED) ) {
|
||||
cfclose(ptr->cfile_ptr);
|
||||
if (ptr->cache != NULL) {
|
||||
if ( ptr->cache ) {
|
||||
vm_free(ptr->cache);
|
||||
ptr->cache = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Assert(ptr->data);
|
||||
if (ptr->data != NULL) {
|
||||
if ( ptr->data ) {
|
||||
vm_free(ptr->data);
|
||||
ptr->data = NULL;
|
||||
}
|
||||
@@ -860,9 +915,11 @@ int anim_free(anim *ptr)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return if an anim is playing or not.
|
||||
*/
|
||||
// ---------------------------------------------------------------------
|
||||
// anim_playing()
|
||||
//
|
||||
// Return if an anim is playing or not.
|
||||
//
|
||||
int anim_playing(anim_instance *ai)
|
||||
{
|
||||
Assert(ai != NULL);
|
||||
@@ -873,28 +930,36 @@ int anim_playing(anim_instance *ai)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Called at the beginning of a mission to initialize any mission dependent anim data.
|
||||
* @todo Redundant?
|
||||
*/
|
||||
// ---------------------------------------------------------------------
|
||||
// anim_level_init()
|
||||
//
|
||||
// Called at the beginning of a mission to initialize any mission dependent
|
||||
// anim data.
|
||||
//
|
||||
void anim_level_init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after the end of a mission to clean up any mission dependent anim data.
|
||||
*/
|
||||
// ---------------------------------------------------------------------
|
||||
// anim_level_close()
|
||||
//
|
||||
// Called after the end of a mission to clean up any mission dependent
|
||||
// anim data.
|
||||
//
|
||||
void anim_level_close()
|
||||
{
|
||||
anim_release_all_instances();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the frames of a .ani file out to disk as .pcx files.
|
||||
* @details Use naming convention: filename0000.pcx, filename0001.pcx etc.
|
||||
*
|
||||
* @return If success 0, or if failed -1
|
||||
*/
|
||||
// ---------------------------------------------------
|
||||
// anim_write_frames_out()
|
||||
//
|
||||
// Write the frames of a .ani file out to disk as .pcx files.
|
||||
// Use naming convention: filename0000.pcx, filename0001.pcx etc.
|
||||
//
|
||||
// return: 0 => success
|
||||
// -1 => failed
|
||||
//
|
||||
int anim_write_frames_out(char *filename)
|
||||
{
|
||||
anim *source_anim;
|
||||
@@ -940,10 +1005,12 @@ int anim_write_frames_out(char *filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display information and statistics about a .ani file.
|
||||
* @details This is called when -i switch is on when running ac.exe
|
||||
*/
|
||||
// ---------------------------------------------------
|
||||
// anim_display_info()
|
||||
//
|
||||
// Display information and statistics about a .ani file.
|
||||
// This is called when -i switch is on when running ac.exe
|
||||
//
|
||||
void anim_display_info(char *real_filename)
|
||||
{
|
||||
CFILE *fp;
|
||||
@@ -969,13 +1036,11 @@ 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);
|
||||
cfread(&tmp, 4, 1, fp);
|
||||
//printf("key frame num: %d,%d\n", key_frame_nums[i],tmp);
|
||||
}
|
||||
|
||||
cfread(&compressed, 4, 1, fp);
|
||||
@@ -1004,7 +1069,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;
|
||||
@@ -24,8 +24,6 @@ typedef struct {
|
||||
anim *anim_info;
|
||||
int x;
|
||||
int y;
|
||||
int base_w;
|
||||
int base_h;
|
||||
int start_at;
|
||||
int stop_at;
|
||||
int screen_id;
|
||||
@@ -52,7 +50,7 @@ void anim_level_init();
|
||||
void anim_level_close();
|
||||
void anim_render_all(int screen_id, float frametime);
|
||||
void anim_render_one(int screen_id, anim_instance *ani, float frametime);
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int max_x = -1, int max_y = -1);
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y);
|
||||
anim_instance *anim_play(anim_play_struct *aps);
|
||||
void anim_ignore_next_frametime();
|
||||
int anim_stop_playing(anim_instance* anim_instance);
|
||||
|
||||
+57
-66
@@ -9,10 +9,12 @@
|
||||
|
||||
|
||||
|
||||
#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;
|
||||
@@ -49,7 +51,6 @@ anim_instance *init_anim_instance(anim *ptr, int bpp)
|
||||
ptr->instance_count++;
|
||||
inst = (anim_instance *) vm_malloc(sizeof(anim_instance));
|
||||
Assert(inst);
|
||||
memset(inst, 0, sizeof(anim_instance));
|
||||
inst->frame_num = -1;
|
||||
inst->last_frame_num = -1;
|
||||
inst->parent = ptr;
|
||||
@@ -100,7 +101,12 @@ int anim_get_next_frame(anim_instance *inst)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bitmap_flags = 0;
|
||||
if (inst->parent->flags & ANF_XPARENT) {
|
||||
// bitmap_flags = BMP_XPARENT;
|
||||
bitmap_flags = 0;
|
||||
} else {
|
||||
bitmap_flags = 0;
|
||||
}
|
||||
|
||||
bpp = 16;
|
||||
if(inst->aa_color != NULL){
|
||||
@@ -162,16 +168,11 @@ ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap
|
||||
return inst->frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pack key frame
|
||||
*
|
||||
* @param frame Frame pixel data to pack
|
||||
* @param save Memory to store packed data to
|
||||
* @param size Number of bytes to pack
|
||||
* @param max Maximum number of packed bytes (size of buffer)
|
||||
* @param compress_type Compress type
|
||||
* @return Actual number of bytes data packed to or -1 if error
|
||||
*/
|
||||
// frame = frame pixel data to pack
|
||||
// save = memory to store packed data to
|
||||
// size = number of bytes to pack
|
||||
// max = maximum number of packed bytes (size of buffer)
|
||||
// returns: actual number of bytes data packed to or -1 if error
|
||||
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
|
||||
{
|
||||
int last = -32768, count = 0;
|
||||
@@ -256,12 +257,14 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
Assert( last != STD_RLE_CODE );
|
||||
// printf("Just packed %d 1 times, since pixel change, no count included\n",last);
|
||||
}
|
||||
else {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
// printf("Just packed %d %d times, since pixel change\n",last,count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +281,8 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
count = 0;
|
||||
// printf("Just packed %d %d times, since count overflow\n",last,count);
|
||||
|
||||
}
|
||||
} // end for
|
||||
|
||||
@@ -289,6 +294,7 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
// printf("Just packed %d 1 times, at end since single pixel, no count\n",last);
|
||||
Assert( last != STD_RLE_CODE );
|
||||
}
|
||||
else {
|
||||
@@ -296,11 +302,13 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
// printf("Just packed %d %d times, at end since pixel change\n",last,count);
|
||||
}
|
||||
}
|
||||
|
||||
Assert(packed_size == (save-dest_start) );
|
||||
return packed_size;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -312,17 +320,12 @@ int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pack frame
|
||||
*
|
||||
* @param frame Frame pixel data to pack
|
||||
* @param frame2 Previous frame's pixel data
|
||||
* @param save Memory to store packed data to
|
||||
* @param size Number of bytes to pack
|
||||
* @param max Maximum number of packed bytes (size of buffer)
|
||||
* @param compress_type Compress type
|
||||
* @return Actual number of bytes data packed to or -1 if error
|
||||
*/
|
||||
// frame = frame pixel data to pack
|
||||
// frame2 = previous frame's pixel data
|
||||
// save = memory to store packed data to
|
||||
// size = number of bytes to pack
|
||||
// max = maximum number of packed bytes (size of buffer)
|
||||
// returns: actual number of bytes data packed to or -1 if error
|
||||
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
|
||||
{
|
||||
int pixel, last = -32768, count = 0, i;
|
||||
@@ -466,6 +469,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:
|
||||
@@ -477,11 +481,7 @@ int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, in
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a 24 bit value to a 16 bit value
|
||||
* @param bit_24 24 bit value
|
||||
* @param bit_16 16 bit value (output)
|
||||
*/
|
||||
// convert a 24 bit value to a 16 bit value
|
||||
void convert_24_to_16(int bit_24, ushort *bit_16)
|
||||
{
|
||||
ubyte *pixel = (ubyte*)&bit_24;
|
||||
@@ -490,10 +490,7 @@ void convert_24_to_16(int bit_24, ushort *bit_16)
|
||||
bm_set_components((ubyte*)bit_16, (ubyte*)&pixel[0], (ubyte*)&pixel[1], (ubyte*)&pixel[2], &alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack a pixel given the passed index and the anim_instance's palette
|
||||
* @return Bytes stuffed
|
||||
*/
|
||||
// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
|
||||
int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
|
||||
{
|
||||
int bit_24;
|
||||
@@ -542,7 +539,7 @@ int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bp
|
||||
}
|
||||
} else {
|
||||
// stuff the 24 bit value
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3); //-V512
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
|
||||
|
||||
// convert to 16 bit
|
||||
convert_24_to_16(bit_24, &bit_16);
|
||||
@@ -573,10 +570,7 @@ int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bp
|
||||
return pixel_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack a pixel given the passed index and the anim_instance's palette
|
||||
* @return Bytes stuffed
|
||||
*/
|
||||
// unpack a pixel given the passed index and the anim_instance's palette, return bytes stuffed
|
||||
int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0, int aabitmap = 0, int bpp = 8)
|
||||
{
|
||||
int bit_24;
|
||||
@@ -626,7 +620,7 @@ int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0,
|
||||
}
|
||||
} else {
|
||||
// stuff the 24 bit value
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3); //-V512
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3);
|
||||
|
||||
// convert to 16 bit
|
||||
convert_24_to_16(bit_24, &bit_16);
|
||||
@@ -655,17 +649,10 @@ int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0,
|
||||
return (pixel_size * count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack frame
|
||||
*
|
||||
* @param ai Animation instance
|
||||
* @param ptr Packed data to unpack
|
||||
* @param frame Where to store unpacked data to
|
||||
* @param size Total number of unpacked pixels requested
|
||||
* @param pal_translate Color translation lookup table (NULL if no palette translation desired)
|
||||
* @param aabitmap
|
||||
* @param bpp
|
||||
*/
|
||||
// ptr = packed data to unpack
|
||||
// frame = where to store unpacked data to
|
||||
// size = total number of unpacked pixels requested
|
||||
// pal_translate = color translation lookup table (NULL if no palette translation desired)
|
||||
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
||||
{
|
||||
int xlate_pal, value, count = 0;
|
||||
@@ -748,6 +735,9 @@ ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte
|
||||
}
|
||||
}
|
||||
else if (*ptr == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
||||
|
||||
// test code, to show unused pixels
|
||||
// memset(frame, 255, size);
|
||||
|
||||
ptr++;
|
||||
while (size > 0) {
|
||||
@@ -838,23 +828,17 @@ ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unknown packing method
|
||||
// Assert(0); // unknown packing method
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack frame from file
|
||||
*
|
||||
* @param ai Animation instance
|
||||
* @param frame Where to store unpacked data to
|
||||
* @param size Total number of unpacked pixels requested
|
||||
* @param pal_translate Color translation lookup table (NULL if no palette translation desired)
|
||||
* @param aabitmap
|
||||
* @param bpp
|
||||
*/
|
||||
// ptr = packed data to unpack
|
||||
// frame = where to store unpacked data to
|
||||
// size = total number of unpacked pixels requested
|
||||
// pal_translate = color translation lookup table (NULL if no palette translation desired)
|
||||
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
||||
{
|
||||
int xlate_pal, value, count = 0;
|
||||
@@ -944,6 +928,9 @@ int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal
|
||||
}
|
||||
}
|
||||
else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
||||
|
||||
// test code, to show unused pixels
|
||||
// memset(frame, 255, size);
|
||||
|
||||
offset++;
|
||||
while (size > 0) {
|
||||
@@ -1046,17 +1033,21 @@ int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set animation palette
|
||||
* @todo Actually convert the frame data to correct palette at this point
|
||||
*/
|
||||
// TODO: actually convert the frame data to correct palette at this point
|
||||
void anim_set_palette(anim *ptr)
|
||||
{
|
||||
int i, xparent_found = 0;
|
||||
|
||||
// create the palette translation look-up table
|
||||
for ( i = 0; i < 256; i++ ) {
|
||||
ptr->palette_translation[i] = (ubyte)i;
|
||||
|
||||
//if ( (ptr->palette[i*3] == ptr->xparent_r) && (ptr->palette[i*3+1] == ptr->xparent_g) && (ptr->palette[i*3+2] == ptr->xparent_b) ) {
|
||||
// ptr->palette_translation[i] = 255;
|
||||
// xparent_found = 1;
|
||||
//} else {
|
||||
// ptr->palette_translation[i] = (ubyte)palette_find( ptr->palette[i*3], ptr->palette[i*3+1], ptr->palette[i*3+2] );
|
||||
ptr->palette_translation[i] = (ubyte)i;
|
||||
//}
|
||||
}
|
||||
|
||||
if ( xparent_found ) {
|
||||
|
||||
@@ -18,11 +18,11 @@ struct CFILE;
|
||||
|
||||
#define ANI_STREAM_CACHE_SIZE 4096
|
||||
|
||||
#define PACKER_CODE 0xEE /// Used by PACKING_METHOD_RLE
|
||||
#define PACKING_METHOD_RLE 0 /// Hoffoss's RLE format
|
||||
#define PACKING_METHOD_RLE_KEY 1 /// Hoffoss's key frame RLE format
|
||||
#define PACKING_METHOD_STD_RLE 2 /// Standard RLE format (high bit is count)
|
||||
#define PACKING_METHOD_STD_RLE_KEY 3 /// Standard RLE format key frame
|
||||
#define PACKER_CODE 0xEE // Use'd by PACKING_METHOD_RLE
|
||||
#define PACKING_METHOD_RLE 0 // Hoffoss's RLE format
|
||||
#define PACKING_METHOD_RLE_KEY 1 // Hoffoss's key frame RLE format
|
||||
#define PACKING_METHOD_STD_RLE 2 // Standard RLE format (high bit is count)
|
||||
#define PACKING_METHOD_STD_RLE_KEY 3 // Standard RLE format key frame
|
||||
|
||||
#define STD_RLE_CODE 0x80
|
||||
|
||||
@@ -71,7 +71,6 @@ typedef struct anim {
|
||||
typedef struct anim_instance {
|
||||
anim_instance *next, *prev;
|
||||
int x,y; // coordinates anim is played at (top left corner of anim)
|
||||
int base_w, base_h; // coordinate scale this anim is played in.
|
||||
vec3d *world_pos; // world (x,y,z) position of explosion
|
||||
float radius; // radius of image, needed for scaling
|
||||
int frame_num; // current frame, or last frame if between frames (first frame is 0)
|
||||
|
||||
+413
-599
File diff suppressed because it is too large.
Load diff
+48
-68
@@ -12,24 +12,28 @@
|
||||
#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
|
||||
|
||||
#define NUM_DEBRIS_SIZES 3
|
||||
#define NUM_DEBRIS_POFS 3 // Number of POFs per debris size
|
||||
#define NUM_DEBRIS_SIZES 3
|
||||
#define NUM_DEBRIS_POFS 3 // Number of POFs per debris size
|
||||
|
||||
#define ASTEROID_TYPE_SMALL 0
|
||||
#define ASTEROID_TYPE_MEDIUM 1
|
||||
#define ASTEROID_TYPE_LARGE 2
|
||||
|
||||
// This is for the asteroid types plus DEBRIS_X_Y
|
||||
// (X is each species and Y is SMALL, MEDIUM, and LARGE)
|
||||
// 20060826 - made dynamic -- taylor
|
||||
//#define MAX_DEBRIS_TYPES ((MAX_SPECIES + 1) * NUM_DEBRIS_SIZES)
|
||||
|
||||
// these should always be equal for the benefit of generic asteroids (c.f. asteroid_page_in)
|
||||
#define MAX_ACTIVE_DEBRIS_TYPES NUM_DEBRIS_SIZES
|
||||
|
||||
@@ -45,69 +49,49 @@ typedef struct asteroid_obj {
|
||||
extern asteroid_obj Asteroid_obj_list;
|
||||
|
||||
|
||||
// Data structure for determining a type and amount of other asteroids an
|
||||
// asteroid will split to when destroyed.
|
||||
typedef struct asteroid_split_info {
|
||||
int asteroid_type;
|
||||
int min;
|
||||
int max;
|
||||
} asteroid_split_info;
|
||||
|
||||
class asteroid_info
|
||||
{
|
||||
public:
|
||||
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
|
||||
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
float max_speed; // cap on speed for asteroid
|
||||
int damage_type_idx; //Damage type of the asteroid
|
||||
int damage_type_idx_sav; // stored value from table used to reset damage_type_idx
|
||||
float inner_rad; // radius within which maximum area effect damage is applied
|
||||
float outer_rad; // radius at which no area effect damage is applied
|
||||
float damage; // maximum damage applied from area effect explosion
|
||||
float blast; // maximum blast impulse from area effect explosion
|
||||
float initial_asteroid_strength; // starting strength of asteroid
|
||||
SCP_vector< asteroid_split_info > split_info;
|
||||
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
|
||||
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
float max_speed; // cap on speed for asteroid
|
||||
int damage_type_idx; //Damage type of the asteroid
|
||||
float inner_rad; // radius within which maximum area effect damage is applied
|
||||
float outer_rad; // radius at which no area effect damage is applied
|
||||
float damage; // maximum damage applied from area effect explosion
|
||||
float blast; // maximum blast impulse from area effect explosion
|
||||
float initial_asteroid_strength; // starting strength of asteroid
|
||||
polymodel *modelp[NUM_DEBRIS_POFS];
|
||||
int model_num[NUM_DEBRIS_POFS];
|
||||
SCP_vector<int> explosion_bitmap_anims;
|
||||
float fireball_radius_multiplier; // the model radius is multiplied by this to determine the fireball size
|
||||
|
||||
asteroid_info( )
|
||||
: num_detail_levels( 0 ), max_speed( 0 ), damage_type_idx( 0 ),
|
||||
damage_type_idx_sav( -1 ), inner_rad( 0 ), outer_rad( 0 ),
|
||||
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
|
||||
fireball_radius_multiplier( -1 )
|
||||
{
|
||||
name[ 0 ] = 0;
|
||||
asteroid_info( )
|
||||
: num_detail_levels( 0 ), max_speed( 0 ), damage_type_idx( -1 ),
|
||||
inner_rad( 0 ), outer_rad( 0 ), damage( 0 ), blast( 0 ),
|
||||
initial_asteroid_strength( 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.
|
||||
#define AF_USED (1<<0) // Set means used.
|
||||
|
||||
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
|
||||
int check_for_wrap; // timestamp to check for asteroid wrapping around field
|
||||
int check_for_collide; // timestamp to check for asteroid colliding with escort ships
|
||||
int final_death_time; // timestamp to swap in new models after explosion starts
|
||||
int final_death_time; // timestamp to swap in new models after explosion starts
|
||||
int collide_objnum; // set to objnum that asteroid will be impacting soon
|
||||
int collide_objsig; // object signature corresponding to collide_objnum
|
||||
vec3d death_hit_pos; // hit pos that caused death
|
||||
int target_objnum; // Yes, hah! Asteroids can have targets. See asteroid_aim_at_target().
|
||||
vec3d death_hit_pos; // hit pos that caused death
|
||||
int target_objnum; // Yes, hah! Asteroids can have targets. See asteroid_aim_at_target().
|
||||
} asteroid;
|
||||
|
||||
|
||||
@@ -124,16 +108,15 @@ typedef enum {
|
||||
} field_type_t;
|
||||
|
||||
typedef struct asteroid_field {
|
||||
vec3d min_bound; // Minimum range of field.
|
||||
vec3d max_bound; // Maximum range of field.
|
||||
float bound_rad;
|
||||
vec3d min_bound; // Minimum range of field.
|
||||
vec3d max_bound; // Maximum range of field.
|
||||
int has_inner_bound;
|
||||
vec3d inner_min_bound;
|
||||
vec3d inner_max_bound;
|
||||
vec3d vel; // Average asteroid moves at this velocity.
|
||||
float speed; // Average speed of field
|
||||
int num_initial_asteroids; // Number of asteroids at creation.
|
||||
field_type_t field_type; // active throws and wraps, passive does not
|
||||
vec3d vel; // Average asteroid moves at this velocity.
|
||||
float speed; // Average speed of field
|
||||
int num_initial_asteroids; // Number of asteroids at creation.
|
||||
field_type_t field_type; // active throws and wraps, passive does not
|
||||
debris_genre_t debris_genre; // type of debris (ship or asteroid) [generic type]
|
||||
int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
|
||||
} asteroid_field;
|
||||
@@ -144,20 +127,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_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);
|
||||
|
||||
+166
-171
@@ -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
|
||||
@@ -54,7 +54,7 @@ int camMovingTime;
|
||||
//float CameraSpeed;
|
||||
bool CinematicStarted, CameraMoving;
|
||||
vec3d cameraPos, cameraTarget;
|
||||
SCP_map<int,int> autopilot_wings;
|
||||
std::map<int,int> autopilot_wings;
|
||||
|
||||
int AutopilotMinEnemyDistance;
|
||||
int AutopilotMinAsteroidDistance;
|
||||
@@ -67,7 +67,14 @@ int start_dist;
|
||||
void autopilot_ai_waypoint_goal_fixup(ai_goal* aigp)
|
||||
{
|
||||
// this function sets wp_index properly;
|
||||
aigp->wp_list = find_matching_waypoint_list(aigp->target_name);
|
||||
for (int i = 0; i < Num_waypoint_lists; i++)
|
||||
{
|
||||
if (!stricmp(aigp->ship_name, Waypoint_lists[i].name))
|
||||
{
|
||||
aigp->wp_index = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,9 +119,7 @@ vec3d *NavPoint::GetPosition()
|
||||
{
|
||||
if (flags & NP_WAYPOINT)
|
||||
{
|
||||
waypoint *wpt = find_waypoint_at_index((waypoint_list*) target_obj, waypoint_num-1);
|
||||
Assert(wpt != NULL);
|
||||
return wpt->get_pos();
|
||||
return &((waypoint_list*) target_obj)->waypoints[waypoint_num-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -122,16 +127,16 @@ vec3d *NavPoint::GetPosition()
|
||||
}
|
||||
}
|
||||
|
||||
char* NavPoint::GetInternalName()
|
||||
char* NavPoint::GetInteralName()
|
||||
{
|
||||
char *NavName;
|
||||
char strtmp[33];
|
||||
|
||||
if (flags & NP_WAYPOINT)
|
||||
{
|
||||
NavName = new char[strlen(((waypoint_list*)target_obj)->get_name())+5];
|
||||
memset(NavName, 0, strlen(((waypoint_list*)target_obj)->get_name())+5);
|
||||
strcpy(NavName, ((waypoint_list*)target_obj)->get_name());
|
||||
NavName = new char[strlen(((waypoint_list*)target_obj)->name)+5];
|
||||
memset(NavName, 0, strlen(((waypoint_list*)target_obj)->name)+5);
|
||||
strcpy(NavName, ((waypoint_list*)target_obj)->name);
|
||||
|
||||
strcat(NavName, ":");
|
||||
sprintf(strtmp, "%d", waypoint_num);
|
||||
@@ -209,7 +214,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 +230,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;
|
||||
@@ -378,7 +372,8 @@ bool StartAutopilot()
|
||||
{
|
||||
capshipPresent = true;
|
||||
|
||||
capIndexes.push_back(i);
|
||||
capIndexes.resize(capIndexes.size()+1);
|
||||
capIndexes[capIndexes.size()-1] = i;
|
||||
// ok.. what size class
|
||||
|
||||
if (Ship_info[Ships[i].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
|
||||
@@ -483,7 +478,7 @@ bool StartAutopilot()
|
||||
{
|
||||
if (Navs[CurrentNav].flags & NP_WAYPOINT)
|
||||
{
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), &Ai_info[Ships[i].ai_index] );
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->name, &Ai_info[Ships[i].ai_index] );
|
||||
//fixup has to wait until after wing goals
|
||||
}
|
||||
else
|
||||
@@ -512,7 +507,7 @@ bool StartAutopilot()
|
||||
if (Navs[CurrentNav].flags & NP_WAYPOINT)
|
||||
{
|
||||
|
||||
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name(), i );
|
||||
ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, AI_GOAL_WAYPOINTS_ONCE, 0, ((waypoint_list*)Navs[CurrentNav].target_obj)->name, i );
|
||||
|
||||
// "fix up" the goal
|
||||
for (j = 0; j < MAX_AI_GOALS; j++)
|
||||
@@ -564,13 +559,13 @@ bool StartAutopilot()
|
||||
// position capships
|
||||
|
||||
vec3d right, front, up, offset;
|
||||
for (SCP_vector<int>::iterator idx = capIndexes.begin(); idx != capIndexes.end(); ++idx)
|
||||
for (i = 0; i < (int)capIndexes.size(); i++)
|
||||
{
|
||||
vm_vec_add(&right, &Autopilot_flight_leader->orient.vec.rvec, &zero);
|
||||
vm_vec_add(&front, &Autopilot_flight_leader->orient.vec.fvec, &zero);
|
||||
vm_vec_add(&up, &Autopilot_flight_leader->orient.vec.uvec, &zero);
|
||||
vm_vec_add(&offset, &zero, &zero);
|
||||
if (Ship_info[Ships[*idx].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
|
||||
if (Ship_info[Ships[capIndexes[i]].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
|
||||
{
|
||||
//0 - below - three lines of position
|
||||
|
||||
@@ -604,7 +599,7 @@ bool StartAutopilot()
|
||||
|
||||
capship_placed[0]++;
|
||||
}
|
||||
else if (Ship_info[Ships[*idx].ship_info_index].flags & SIF_CORVETTE)
|
||||
else if (Ship_info[Ships[capIndexes[i]].ship_info_index].flags & SIF_CORVETTE)
|
||||
{
|
||||
//1 above - 3 lines of position
|
||||
// front/back to zero
|
||||
@@ -713,11 +708,11 @@ bool StartAutopilot()
|
||||
// global scale the position by 50%
|
||||
//vm_vec_scale(&offset, 1.5);
|
||||
|
||||
vm_vec_add(&Objects[Ships[*idx].objnum].pos, &Autopilot_flight_leader->pos, &offset);
|
||||
vm_vec_add(&Objects[Ships[capIndexes[i]].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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -895,7 +890,7 @@ void EndAutoPilot()
|
||||
if (Navs[CurrentNav].flags & NP_WAYPOINT)
|
||||
{
|
||||
goal = AI_GOAL_WAYPOINTS_ONCE;
|
||||
goal_name = ((waypoint_list*)Navs[CurrentNav].target_obj)->get_name();
|
||||
goal_name = ((waypoint_list*)Navs[CurrentNav].target_obj)->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -928,7 +923,7 @@ void EndAutoPilot()
|
||||
{
|
||||
ai_goal *aigp = &Ai_info[Ships[i].ai_index].goals[j];
|
||||
|
||||
if ( ((aigp->target_name != NULL) && !stricmp(aigp->target_name, goal_name))
|
||||
if ( ((aigp->ship_name != NULL) && !stricmp(aigp->ship_name, goal_name))
|
||||
&& (aigp->ai_mode == goal) )
|
||||
{
|
||||
ai_remove_ship_goal(&Ai_info[Ships[i].ai_index], j);
|
||||
@@ -941,7 +936,7 @@ void EndAutoPilot()
|
||||
{
|
||||
ai_goal *aigp = &Wings[Ships[i].wingnum].ai_goals[j];
|
||||
|
||||
if ( ((aigp->target_name != NULL) && !stricmp(aigp->target_name, goal_name))
|
||||
if ( ((aigp->ship_name != NULL) && !stricmp(aigp->ship_name, goal_name))
|
||||
&& (aigp->ai_mode == goal) )
|
||||
{
|
||||
aigp->ai_mode = AI_GOAL_NONE;
|
||||
@@ -965,7 +960,7 @@ void EndAutoPilot()
|
||||
{
|
||||
ai_goal *aigp = &Wings[i].ai_goals[j];
|
||||
|
||||
if ( ((aigp->target_name != NULL) && !stricmp(aigp->target_name, goal_name))
|
||||
if ( ((aigp->ship_name != NULL) && !stricmp(aigp->ship_name, goal_name))
|
||||
&& (aigp->ai_mode == goal) )
|
||||
{
|
||||
aigp->ai_mode = AI_GOAL_NONE;
|
||||
@@ -995,7 +990,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 +1044,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 +1203,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);
|
||||
@@ -1228,11 +1219,11 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
audio_handle = -1;
|
||||
}
|
||||
|
||||
if (msg[0] != '\0' && strcmp(msg, "none"))
|
||||
if (strlen(msg) != 0 && strcmp(msg, "none"))
|
||||
change_message("autopilot builtin message", msg, -1, 0);
|
||||
|
||||
// load sound
|
||||
if ((snd != NULL) && (snd[0] != '\0' && !strcmp(snd, "none")))
|
||||
if (snd != NULL || strlen(snd) == 0 || !strcmp(snd, "none"))
|
||||
{
|
||||
audio_handle = audiostream_open(snd, ASF_MENUMUSIC );
|
||||
}
|
||||
@@ -1243,7 +1234,7 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
audiostream_play(audio_handle, (Master_event_music_volume * aav_music_volume), 0);
|
||||
}
|
||||
|
||||
if (msg[0] != '\0' && strcmp(msg, "none"))
|
||||
if (strlen(msg) != 0 && strcmp(msg, "none"))
|
||||
message_training_queue("autopilot builtin message", timestamp(0), 5); // display message for five seconds
|
||||
}
|
||||
|
||||
@@ -1251,9 +1242,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 +1260,75 @@ void NavSystem_Init()
|
||||
|
||||
void parse_autopilot_table(char *filename)
|
||||
{
|
||||
SCP_vector<SCP_string> lines;
|
||||
int rval;
|
||||
SCP_vector<std::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 +1338,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 +1362,7 @@ bool DelNavPoint(char *Nav)
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool DelNavPoint(int nav)
|
||||
{
|
||||
if (nav != -1)
|
||||
@@ -1372,7 +1375,7 @@ bool DelNavPoint(int nav)
|
||||
}
|
||||
|
||||
}
|
||||
Navs[MAX_NAVPOINTS-1].clear();
|
||||
ZeroNav(MAX_NAVPOINTS-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1400,7 +1403,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,12 +1449,20 @@ 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));
|
||||
|
||||
tnav.target_obj = find_matching_waypoint_list(WP_Path);
|
||||
|
||||
for (i = 0; i < Num_waypoint_lists; i++)
|
||||
{
|
||||
if (!stricmp(WP_Path, Waypoint_lists[i].name))
|
||||
{
|
||||
tnav.target_obj = (void *)&Waypoint_lists[i];
|
||||
}
|
||||
}
|
||||
|
||||
tnav.waypoint_num = node;
|
||||
|
||||
// copy it into it's location
|
||||
@@ -1569,23 +1580,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;
|
||||
}
|
||||
|
||||
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
@@ -1599,7 +1594,7 @@ unsigned int DistanceTo(char *nav)
|
||||
|
||||
unsigned int DistanceTo(int nav)
|
||||
{
|
||||
if (nav >= MAX_NAVPOINTS || nav < 0)
|
||||
if (nav >= MAX_NAVPOINTS && nav < 0)
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
return (uint)vm_vec_dist_quick(&Player_obj->pos, Navs[nav].GetPosition());
|
||||
@@ -1616,7 +1611,7 @@ bool IsVisited(char *nav)
|
||||
|
||||
bool IsVisited(int nav)
|
||||
{
|
||||
if (nav >= MAX_NAVPOINTS || nav < 0)
|
||||
if (nav >= MAX_NAVPOINTS && nav < 0)
|
||||
return 0;
|
||||
|
||||
if (Navs[nav].flags & NP_VISITED)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "object/object.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
// milliseconds between updates
|
||||
@@ -17,8 +16,8 @@
|
||||
|
||||
#define MAX_NAVPOINTS 8
|
||||
|
||||
#define NP_WAYPOINT 0x0001 // Nav Point is bound to the position of a single node of a waypoint path
|
||||
#define NP_SHIP 0x0002 // Nav Point is bound to the position of a certain ship
|
||||
#define NP_WAYPOINT 0x0001 // Nav Point is bound to the poistion of a single node of a waypoint path
|
||||
#define NP_SHIP 0x0002 // Nav Point is bound to the poisiton of a certain ship
|
||||
#define NP_HIDDEN 0x0004 // Nav Point doesn't show on map and isn't selectable
|
||||
#define NP_NOACCESS 0x0008 // Nav Point isn't selectable
|
||||
#define NP_VISITED 0x0100 // Whether we've been within 1,000 meters of this waypoint
|
||||
@@ -26,26 +25,16 @@
|
||||
#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;
|
||||
int waypoint_num; //only used when flags & NP_WAYPOINT
|
||||
|
||||
vec3d *GetPosition();
|
||||
char* GetInternalName();
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_NavName[0] = 0;
|
||||
flags = 0;
|
||||
|
||||
target_obj = NULL;
|
||||
waypoint_num = -1;
|
||||
}
|
||||
char* GetInteralName();
|
||||
};
|
||||
|
||||
|
||||
@@ -70,7 +59,7 @@ extern int CurrentNav;
|
||||
extern NavPoint Navs[MAX_NAVPOINTS];
|
||||
extern NavMessage NavMsgs[NP_NUM_MESSAGES];
|
||||
extern int LockAPConv;
|
||||
extern SCP_map<int,int> autopilot_wings;
|
||||
extern std::map<int,int> autopilot_wings;
|
||||
|
||||
// Cycles through the NavPoint List
|
||||
bool Sel_NextNav();
|
||||
@@ -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
|
||||
ubyte fps; // used for animation -- frames per second
|
||||
int keyframe; // used for animation -- keyframe info
|
||||
|
||||
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__
|
||||
+2479
-2938
File diff suppressed because it is too large.
Load diff
+211
-622
@@ -1,701 +1,290 @@
|
||||
#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
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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
|
||||
// this is causing problems - let's UP IT -- Kazan
|
||||
// bumped from 3500 to 4500 2004/09/21 - taylor
|
||||
// bumped to 4750 2005/02/03 - taylor
|
||||
//#define MAX_BITMAPS 3500 // How many bitmaps the game can handle
|
||||
#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
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
|
||||
float map_texture_address(float address);
|
||||
public:
|
||||
bitmap_lookup(int bitmap_num);
|
||||
~bitmap_lookup();
|
||||
// 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);
|
||||
|
||||
bool valid();
|
||||
// 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);
|
||||
|
||||
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);
|
||||
};
|
||||
// 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 );
|
||||
|
||||
/**
|
||||
* @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);
|
||||
// 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 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
|
||||
*/
|
||||
int bm_load(const SCP_string& filename);
|
||||
// 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 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);
|
||||
// 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 );
|
||||
|
||||
/**
|
||||
* 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);
|
||||
//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 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.
|
||||
// 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 );
|
||||
|
||||
* @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);
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
//gets the image type
|
||||
ubyte bm_get_type(int handle);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
// Unlocks a bitmap
|
||||
extern void bm_unlock( int bitmapnum );
|
||||
|
||||
/**
|
||||
* @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);
|
||||
//WMC - Returns 0 if invalid, nonzero if valid
|
||||
extern int bm_is_valid(int handle);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
// 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 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
|
||||
// get filename
|
||||
extern void bm_get_filename(int bitmapnum, char *filename);
|
||||
|
||||
* @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);
|
||||
// resyncs all the bitmap palette
|
||||
extern void bm_update();
|
||||
|
||||
/**
|
||||
* @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);
|
||||
// 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 Returns the image type of the given bitmap handle
|
||||
*/
|
||||
BM_TYPE bm_get_type(int handle);
|
||||
// call to get the palette for a bitmap
|
||||
void bm_get_palette(int n, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
// 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 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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
+255
-193
@@ -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
|
||||
@@ -24,12 +24,16 @@ SCP_vector<camera*> Cameras;
|
||||
camid Current_camera;
|
||||
camid Main_camera;
|
||||
|
||||
//*************************INTERNAL FUNCS*************************
|
||||
//static avd_camera *cam_upgrade_to_avd(camera *cam);
|
||||
|
||||
//*************************CLASS: camera*************************
|
||||
//This is where the camera class beings! :D
|
||||
camera::camera(char *in_name, int in_signature)
|
||||
{
|
||||
set_name(in_name);
|
||||
sig = in_signature;
|
||||
// flags = CAM_DEFAULT_FLAGS;
|
||||
|
||||
reset();
|
||||
}
|
||||
@@ -71,16 +75,36 @@ void camera::reset()
|
||||
pos_y.clear();
|
||||
pos_z.clear();
|
||||
|
||||
/*
|
||||
ori_p.clear();
|
||||
ori_b.clear();
|
||||
ori_h.clear();
|
||||
*/
|
||||
/*
|
||||
ori_progress.clear();
|
||||
ori_initial = ori_final = vmd_identity_matrix;
|
||||
*/
|
||||
for(int i = 0; i < 9; i++)
|
||||
{
|
||||
ori[i].clear();
|
||||
ori[i].set(vmd_identity_matrix.a1d[i]);
|
||||
}
|
||||
/*
|
||||
flags = CAM_DEFAULT_FLAGS;
|
||||
|
||||
desired_position = position = vmd_zero_vector;
|
||||
|
||||
translation_velocity = translation_vel_limit = translation_acc_limit = vmd_zero_vector;
|
||||
|
||||
vm_set_identity(&orientation);
|
||||
vm_set_identity(&desired_orientation);
|
||||
rotation_rate = rotation_vel_limit = rotation_acc_limit = vmd_zero_vector;
|
||||
*/
|
||||
}
|
||||
|
||||
void camera::set_name(char *in_name)
|
||||
{
|
||||
if(in_name != NULL)
|
||||
if(name != NULL)
|
||||
strncpy(name, in_name, NAME_LENGTH-1);
|
||||
}
|
||||
|
||||
@@ -109,27 +133,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)
|
||||
@@ -141,19 +144,15 @@ void camera::set_object_target(object *objp, int n_object_target_submodel)
|
||||
object_target_submodel = n_object_target_submodel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function receives the already-modified current position value.
|
||||
* It should be replaced or added to as the custom function modifier sees fit.
|
||||
*/
|
||||
//Custom function receives the already-modified current position value.
|
||||
//It should be replaced or added to as the custom function modifier sees fit.
|
||||
void camera::set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *camera_pos))
|
||||
{
|
||||
func_custom_position = n_func_custom_position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function receives the already-modified current orientation value.
|
||||
* It should be replaced or added to as the custom function modifier sees fit.
|
||||
*/
|
||||
//Custom function receives the already-modified current orientation value.
|
||||
//It should be replaced or added to as the custom function modifier sees fit.
|
||||
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *camera_ori))
|
||||
{
|
||||
func_custom_orientation = n_func_custom_orientation;
|
||||
@@ -161,7 +160,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 +193,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++)
|
||||
@@ -213,6 +212,26 @@ void camera::set_rotation(matrix *in_orientation, float in_rotation_time, float
|
||||
|
||||
for(int i = 0; i < 9; i++)
|
||||
ori[i].setAVD(in_orientation->a1d[i], in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time, 0.0f);
|
||||
//WMC - This stationary check is here because it's a lot more
|
||||
//accurate to directly save the matrix, if we've been provided one.
|
||||
//IMPORTANT: Without this chunk, the HUD and view waves around with
|
||||
// the main camera.
|
||||
/*
|
||||
angles a;
|
||||
vm_extract_angles_matrix(&a, in_orientation);
|
||||
if(in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f)
|
||||
{
|
||||
c_ori = *in_orientation;
|
||||
ori_p.set(a.p);
|
||||
ori_b.set(a.b);
|
||||
ori_h.set(a.h);
|
||||
flags |= CAM_STATIONARY_ORI;
|
||||
return;
|
||||
}
|
||||
|
||||
//Continue on
|
||||
this->set_rotation(&a, in_rotation_time, in_rotation_acceleration_time);
|
||||
*/
|
||||
}
|
||||
|
||||
void camera::set_rotation(angles *in_angles, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
|
||||
@@ -220,6 +239,33 @@ void camera::set_rotation(angles *in_angles, float in_rotation_time, float in_ro
|
||||
matrix mtx = IDENTITY_MATRIX;
|
||||
vm_rotate_matrix_by_angles(&mtx, in_angles);
|
||||
this->set_rotation(&mtx, in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time);
|
||||
/*
|
||||
if(in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f)
|
||||
{
|
||||
ori_p.set(in_angles->p);
|
||||
ori_b.set(in_angles->b);
|
||||
ori_h.set(in_angles->h);
|
||||
|
||||
c_ori = vmd_identity_matrix;
|
||||
vm_rotate_matrix_by_angles(&c_ori, in_angles);
|
||||
|
||||
flags |= CAM_STATIONARY_ORI;
|
||||
return;
|
||||
}
|
||||
|
||||
flags &= ~CAM_STATIONARY_ORI;
|
||||
if(in_angles == NULL)
|
||||
{
|
||||
ori_p.setVD(in_rotation_time, in_rotation_acceleration_time, 0.0f);
|
||||
ori_b.setVD(in_rotation_time, in_rotation_acceleration_time, 0.0f);
|
||||
ori_h.setVD(in_rotation_time, in_rotation_acceleration_time, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
ori_p.setAVD(in_angles->p, in_rotation_time, in_rotation_acceleration_time, in_rotation_acceleration_time, 0.0f);
|
||||
ori_b.setAVD(in_angles->b, in_rotation_time, in_rotation_acceleration_time, in_rotation_acceleration_time, 0.0f);
|
||||
ori_h.setAVD(in_angles->h, in_rotation_time, in_rotation_acceleration_time, in_rotation_acceleration_time, 0.0f);
|
||||
*/
|
||||
}
|
||||
|
||||
void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
|
||||
@@ -248,6 +294,27 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
|
||||
void camera::set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time)
|
||||
{
|
||||
Error(LOCATION, "This function is disabled until further notice.");
|
||||
/*
|
||||
ori_p.setVD(in_acceleration_time, in_acceleration_time, in_rotation_rate->p);
|
||||
ori_b.setVD(in_acceleration_time, in_acceleration_time, in_rotation_rate->b);
|
||||
ori_h.setVD(in_acceleration_time, in_acceleration_time, in_rotation_rate->h);
|
||||
*/
|
||||
|
||||
/*if(in_rotation_rate == NULL)
|
||||
{
|
||||
rotation_rate.p = rotation_rate.b = rotation_rate.h = 0.0f;
|
||||
|
||||
rotation_rate_delta_time = rotation_rate_delta_time_left = in_rotation_acceleration_time = 0.0f;
|
||||
rotation_rate_decel_time_til = -1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
rotation_rate_delta_time = rotation_rate_delta_time_left = in_rotation_acceleration_time;
|
||||
rotation_rate_decel_time_til = -1.0f;
|
||||
|
||||
rotation_rate_delta.p = in_rotation_rate->p / in_rotation_acceleration_time;
|
||||
rotation_rate_delta.b = in_rotation_rate->b / in_rotation_acceleration_time;
|
||||
rotation_rate_delta.h = in_rotation_rate->h / in_rotation_acceleration_time;*/
|
||||
}
|
||||
|
||||
void camera::do_frame(float in_frametime)
|
||||
@@ -291,14 +358,12 @@ float camera::get_fov()
|
||||
return c_fov;
|
||||
}
|
||||
|
||||
eye* get_submodel_eye(polymodel *pm, int submodel_num);
|
||||
void camera::get_info(vec3d *position, matrix *orientation)
|
||||
{
|
||||
//WTF?
|
||||
if(position == NULL && orientation == NULL)
|
||||
return;
|
||||
|
||||
eye* eyep = NULL;
|
||||
vec3d host_normal;
|
||||
|
||||
//POSITION
|
||||
if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
|
||||
{
|
||||
@@ -327,20 +392,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 +401,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 +413,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,25 +442,27 @@ 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
|
||||
{
|
||||
c_ori = vmd_identity_matrix;
|
||||
}
|
||||
|
||||
//Do human interaction
|
||||
//WMC - Nevermind for now, maybe toggleable later.
|
||||
/*
|
||||
if ( Viewer_obj == object_host.objp || Viewer_mode & VM_CHASE ) {
|
||||
if ( Viewer_mode & VM_PADLOCK_ANY ) {
|
||||
player_get_padlock_orient(&c_ori);
|
||||
} else {
|
||||
compute_slew_matrix(&c_ori, &Viewer_slew_angles);
|
||||
}
|
||||
}*/
|
||||
|
||||
matrix mtxA = c_ori;
|
||||
matrix mtxB = IDENTITY_MATRIX;
|
||||
float pos = 0.0f;
|
||||
@@ -421,16 +474,24 @@ void camera::get_info(vec3d *position, matrix *orientation)
|
||||
vm_matrix_x_matrix(&c_ori, &mtxA, &mtxB);
|
||||
|
||||
vm_orthogonalize_matrix(&c_ori);
|
||||
/*
|
||||
angles a;
|
||||
ori_p.get(&a.p, NULL);
|
||||
ori_b.get(&a.b, NULL);
|
||||
ori_h.get(&a.h, NULL);
|
||||
|
||||
vm_rotate_matrix_by_angles(&c_ori, &a);
|
||||
*/
|
||||
//vm_angles_2_matrix(&c_ori, &a);
|
||||
}
|
||||
//Do custom orientation stuff, if needed
|
||||
if(func_custom_orientation != NULL && !target_set)
|
||||
if(func_custom_orientation != NULL)
|
||||
{
|
||||
func_custom_orientation(this, &c_ori);
|
||||
}
|
||||
*orientation = c_ori;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************warp_camera*************************
|
||||
warp_camera::warp_camera()
|
||||
{
|
||||
@@ -443,7 +504,16 @@ warp_camera::warp_camera(object *objp)
|
||||
vec3d object_pos = objp->pos;
|
||||
matrix tmp;
|
||||
ship_get_eye(&object_pos, &tmp, objp);
|
||||
|
||||
/*
|
||||
//matrix tmp_m = vmd_identity_matrix;
|
||||
camid cid = ship_get_eye( objp );
|
||||
if(cid.isValid())
|
||||
{
|
||||
camera *cam = cid.getCamera();
|
||||
cam->get_info(&player_pos, NULL);
|
||||
//tmp_m = *cam->get_orientation();
|
||||
}
|
||||
*/
|
||||
vm_vec_scale_add2( &object_pos, &Player_obj->orient.vec.rvec, 0.0f );
|
||||
vm_vec_scale_add2( &object_pos, &Player_obj->orient.vec.uvec, 0.952f );
|
||||
vm_vec_scale_add2( &object_pos, &Player_obj->orient.vec.fvec, -1.782f );
|
||||
@@ -489,6 +559,7 @@ void warp_camera::set_velocity( vec3d *in_vel, bool instantaneous )
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
void warp_camera::do_frame(float in_frametime)
|
||||
{
|
||||
vec3d new_vel, delta_pos;
|
||||
@@ -499,6 +570,8 @@ void warp_camera::do_frame(float in_frametime)
|
||||
|
||||
c_vel = new_vel;
|
||||
|
||||
// mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
|
||||
|
||||
vm_vec_add2( &c_pos, &delta_pos );
|
||||
|
||||
float ot = c_time+0.0f;
|
||||
@@ -515,9 +588,12 @@ 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);
|
||||
|
||||
//mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
|
||||
|
||||
//mprintf(( "Changing velocity!\n" ));
|
||||
this->set_velocity( &tmp, 0 );
|
||||
}
|
||||
|
||||
@@ -540,17 +616,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,27 +627,29 @@ 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;
|
||||
|
||||
if (in_text != NULL && in_text[0] != '\0')
|
||||
char text_buf[256];
|
||||
if (in_text != NULL && strlen(in_text) > 0)
|
||||
{
|
||||
text_buf = in_text;
|
||||
sexp_replace_variable_names_with_values(text_buf);
|
||||
in_text = text_buf.c_str();
|
||||
strcpy(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
|
||||
if ( (in_text != NULL) && (in_text[0] != '\0') ) {
|
||||
if ( (in_text != NULL) && (strlen(in_text) > 0) ) {
|
||||
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);
|
||||
std::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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +665,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
|
||||
fade_time = fl_abs(in_fade_time);
|
||||
|
||||
//Setup image
|
||||
if ( (in_imageanim != NULL) && (in_imageanim[0] != '\0') )
|
||||
if ( (in_imageanim != NULL) && (strlen(in_imageanim) > 0) )
|
||||
{
|
||||
image_id = bm_load(in_imageanim);
|
||||
|
||||
@@ -653,20 +722,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;
|
||||
@@ -722,10 +791,9 @@ void subtitle::do_frame(float frametime)
|
||||
int x = text_pos.x;
|
||||
int y = text_pos.y;
|
||||
|
||||
|
||||
for(SCP_vector<SCP_string>::iterator line = text_lines.begin(); line != text_lines.end(); ++line)
|
||||
for(unsigned int i = 0; i < text_lines.size(); i++)
|
||||
{
|
||||
gr_string(x, y, (char*)line->c_str(), GR_RESIZE_NONE);
|
||||
gr_string(x, y, (char*)text_lines[i].c_str(), false);
|
||||
y += font_height;
|
||||
}
|
||||
|
||||
@@ -746,18 +814,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,8 +843,11 @@ subtitle::~subtitle()
|
||||
|
||||
void subtitle::clone(const subtitle &sub)
|
||||
{
|
||||
uint i = 0;
|
||||
|
||||
text_lines = sub.text_lines;
|
||||
for (i = 0; i < sub.text_lines.size(); i++) {
|
||||
text_lines.push_back(sub.text_lines[i]);
|
||||
}
|
||||
text_fontnum = sub.text_fontnum;
|
||||
|
||||
// copy the structs
|
||||
@@ -850,7 +921,7 @@ int camid::getSignature()
|
||||
|
||||
bool camid::isValid()
|
||||
{
|
||||
if(idx >= Cameras.size())
|
||||
if(idx < 0 || idx >= Cameras.size())
|
||||
return false;
|
||||
|
||||
if(Cameras[idx] == NULL)
|
||||
@@ -873,8 +944,13 @@ void cam_close()
|
||||
{
|
||||
//Set Current_camera to nothing
|
||||
Current_camera = camid();
|
||||
for (auto ii = Cameras.begin(); ii != Cameras.end(); ++ii) {
|
||||
delete * ii;
|
||||
for(unsigned int i = 0; i < Cameras.size(); i++)
|
||||
{
|
||||
if(Cameras[i] != NULL)
|
||||
{
|
||||
delete Cameras[i];
|
||||
Cameras[i] = NULL;
|
||||
}
|
||||
}
|
||||
Cameras.clear();
|
||||
}
|
||||
@@ -908,9 +984,29 @@ camid cam_create(char *n_name, vec3d *n_pos, matrix *n_ori, object *n_object, in
|
||||
strncpy(buf, n_name, NAME_LENGTH-1);
|
||||
|
||||
//Find a free slot
|
||||
cam = new camera(buf, sig);
|
||||
cid = camid(Cameras.size(), sig);
|
||||
Cameras.push_back(cam);
|
||||
for(uint i = 0; i < Cameras.size(); i++)
|
||||
{
|
||||
if(Cameras[i] == NULL)
|
||||
{
|
||||
cam = new camera(buf, sig);
|
||||
cid = camid(i, sig);
|
||||
Cameras[i] = cam;
|
||||
break;
|
||||
}
|
||||
else if(Cameras[i]->is_empty())
|
||||
{
|
||||
delete Cameras[i];
|
||||
cam = new camera(buf, sig);
|
||||
cid = camid(i, sig);
|
||||
Cameras[i] = cam;
|
||||
}
|
||||
}
|
||||
if(cam == NULL)
|
||||
{
|
||||
cam = new camera(buf, sig);
|
||||
cid = camid(Cameras.size(), sig);
|
||||
Cameras.push_back(cam);
|
||||
}
|
||||
|
||||
//Set attributes
|
||||
if(n_pos != NULL)
|
||||
@@ -933,7 +1029,7 @@ void cam_delete(camid cid)
|
||||
|
||||
void cam_do_frame(float frametime)
|
||||
{
|
||||
size_t i,size=Cameras.size();
|
||||
unsigned int i,size=Cameras.size();
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
if(Cameras[i] != NULL)
|
||||
@@ -943,7 +1039,7 @@ void cam_do_frame(float frametime)
|
||||
|
||||
camid cam_get_camera(uint idx)
|
||||
{
|
||||
if(idx >= Cameras.size())
|
||||
if(idx < 0 || idx >= Cameras.size())
|
||||
return camid();
|
||||
|
||||
return camid(idx, Cameras[idx]->get_signature());
|
||||
@@ -959,12 +1055,10 @@ uint cam_get_num()
|
||||
return Cameras.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up camera by name, returns -1 on failure
|
||||
*/
|
||||
//Looks up camera by name, returns -1 on failure
|
||||
camid cam_lookup(char *name)
|
||||
{
|
||||
size_t i, size=Cameras.size();
|
||||
unsigned int i,size=Cameras.size();
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
if(Cameras[i] != NULL && !stricmp(Cameras[i]->get_name(), name))
|
||||
@@ -987,15 +1081,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 +1094,37 @@ 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;
|
||||
}
|
||||
|
||||
//Functions must delete the original camera after calling this function.
|
||||
//Note that due to the esoteric nature of this function, it should not
|
||||
//be used outside camera.cpp
|
||||
/*
|
||||
static avd_camera *cam_upgrade_to_avd(camera *cam)
|
||||
{
|
||||
for(uint i = 0; i < Cameras.size(); i++)
|
||||
{
|
||||
hud_set_draw(Camera_hud_draw_value);
|
||||
Camera_hud_draw_saved = false;
|
||||
if(Cameras[i] == cam)
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == Cameras.size())
|
||||
return NULL;
|
||||
|
||||
avd_camera *avdcam = new avd_camera(cam);
|
||||
|
||||
//Make the switch
|
||||
Cameras[i] = avdcam;
|
||||
|
||||
return avdcam;
|
||||
}
|
||||
*/
|
||||
|
||||
void subtitles_init()
|
||||
{
|
||||
//Do nothing!!
|
||||
}
|
||||
|
||||
void subtitles_close()
|
||||
@@ -1017,75 +1134,20 @@ void subtitles_close()
|
||||
|
||||
void subtitles_do_frame(float frametime)
|
||||
{
|
||||
SCP_vector<subtitle>::iterator sub;
|
||||
for(sub = Subtitles.begin(); sub != Subtitles.end(); ++sub)
|
||||
unsigned int i,size=Subtitles.size();
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
if ( !sub->is_post_shaded( ) )
|
||||
sub->do_frame(frametime);
|
||||
if ( !Subtitles[i].is_post_shaded( ) )
|
||||
Subtitles[i].do_frame(frametime);
|
||||
}
|
||||
}
|
||||
|
||||
void subtitles_do_frame_post_shaded(float frametime)
|
||||
{
|
||||
SCP_vector<subtitle>::iterator sub;
|
||||
for(sub = Subtitles.begin(); sub != Subtitles.end(); ++sub)
|
||||
unsigned int i,size=Subtitles.size();
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
if ( sub->is_post_shaded( ) )
|
||||
sub->do_frame(frametime);
|
||||
if ( Subtitles[i].is_post_shaded( ) )
|
||||
Subtitles[i].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;
|
||||
}
|
||||
}
|
||||
+15
-9
@@ -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>
|
||||
|
||||
@@ -33,9 +33,17 @@ protected:
|
||||
void (*func_custom_orientation)(camera *cam, matrix *ori);
|
||||
|
||||
avd_movement fov;
|
||||
|
||||
avd_movement pos_x;
|
||||
avd_movement pos_y;
|
||||
avd_movement pos_z;
|
||||
|
||||
//avd_movement ori_p;
|
||||
//avd_movement ori_b;
|
||||
//avd_movement ori_h;
|
||||
//avd_movement ori_progress;
|
||||
//matrix ori_initial;
|
||||
//matrix ori_final;
|
||||
avd_movement ori[9];
|
||||
|
||||
//Cache stuff
|
||||
@@ -116,7 +124,7 @@ class subtitle
|
||||
private:
|
||||
void clone(const subtitle &sub);
|
||||
|
||||
SCP_vector<SCP_string> text_lines;
|
||||
SCP_vector<std::string> text_lines;
|
||||
struct { int x; int y; } text_pos;
|
||||
|
||||
float display_time;
|
||||
@@ -137,8 +145,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 +176,7 @@ 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_init();
|
||||
void subtitles_close();
|
||||
void subtitles_do_frame(float frametime);
|
||||
void subtitles_do_frame_post_shaded(float frametime);
|
||||
|
||||
+245
-324
@@ -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
|
||||
@@ -52,7 +52,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
|
||||
// Root must be index 1!!
|
||||
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_DATA, "data", ".cfg .log .txt", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
|
||||
@@ -78,7 +78,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
|
||||
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .ibx .tsb", CF_TYPE_DATA }, //clr=cached color
|
||||
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
|
||||
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg", CF_TYPE_DATA },
|
||||
@@ -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;
|
||||
|
||||
@@ -998,10 +961,6 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
|
||||
cfbp->data = NULL;
|
||||
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 +978,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;
|
||||
@@ -1039,10 +998,6 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
|
||||
cfbp->data = NULL;
|
||||
cfbp->fp = fp;
|
||||
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 );
|
||||
|
||||
@@ -1059,9 +1014,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;
|
||||
@@ -1080,17 +1035,12 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
|
||||
|
||||
cfp = &Cfile_list[cfile_block_index];
|
||||
cfp->id = cfile_block_index;
|
||||
cfp->version = 0;
|
||||
cfbp->max_read_len = 0;
|
||||
cfbp->fp = NULL;
|
||||
#if defined _WIN32
|
||||
cfbp->hInFile = hFile;
|
||||
#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);
|
||||
@@ -1148,22 +1098,6 @@ void cf_set_version( CFILE * cfile, int version )
|
||||
cfile->version = version;
|
||||
}
|
||||
|
||||
// cutoff point where cfread() will throw an error when it hits this limit
|
||||
// if 'len' is 0 then this check will be disabled
|
||||
void cf_set_max_read_len( CFILE * cfile, size_t len )
|
||||
{
|
||||
Assert( cfile != NULL );
|
||||
Assert( (cfile->id >= 0) && (cfile->id < MAX_CFILE_BLOCKS) );
|
||||
|
||||
Cfile_block *cb = &Cfile_block_list[cfile->id];
|
||||
|
||||
if (len) {
|
||||
cb->max_read_len = cb->raw_position + len;
|
||||
} else {
|
||||
cb->max_read_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// routines to read basic data types from CFILE's. Put here to
|
||||
// simplify mac/pc reading from cfiles.
|
||||
|
||||
@@ -1312,7 +1246,7 @@ void cfread_string_len(char *buf,int n, CFILE *file)
|
||||
{
|
||||
int len;
|
||||
len = cfread_int(file);
|
||||
Assertion( (len < n), "len: %i, n: %i", len, n );
|
||||
Assert( len < n );
|
||||
if (len)
|
||||
cfread(buf, len, 1, file);
|
||||
|
||||
@@ -1383,7 +1317,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);
|
||||
@@ -1395,7 +1329,7 @@ int cfwrite_string(const char *buf, CFILE *file)
|
||||
return cfwrite_char(0, file); // write out NULL termination
|
||||
}
|
||||
|
||||
int cfwrite_string_len(const char *buf, CFILE *file)
|
||||
int cfwrite_string_len(char *buf, CFILE *file)
|
||||
{
|
||||
int len = strlen(buf);
|
||||
|
||||
@@ -1431,7 +1365,7 @@ int cfilelength( CFILE * cfile )
|
||||
// returns: number of full elements actually written
|
||||
//
|
||||
//
|
||||
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
int cfwrite(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
{
|
||||
if(!cf_is_valid(cfile))
|
||||
return 0;
|
||||
@@ -1453,22 +1387,18 @@ int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
size_t bytes_written = 0;
|
||||
size_t size = elsize * nelem;
|
||||
int result = 0;
|
||||
|
||||
bytes_written = fwrite(buf, 1, size, cb->fp);
|
||||
result = fwrite(buf, elsize, nelem, cb->fp);
|
||||
|
||||
//WMC - update filesize and position
|
||||
if (bytes_written > 0) {
|
||||
cb->size += bytes_written;
|
||||
cb->raw_position += bytes_written;
|
||||
if(result > 0)
|
||||
{
|
||||
cb->size = filelength(fileno(cb->fp));
|
||||
cb->raw_position += result;
|
||||
}
|
||||
|
||||
#if defined(CHECK_SIZE) && !defined(NDEBUG)
|
||||
Assert( cb->size == filelength(fileno(cb->fp)) );
|
||||
#endif
|
||||
|
||||
return ((int)bytes_written / elsize);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1504,14 +1434,10 @@ int cfputc(int c, CFILE *cfile)
|
||||
//WMC - update filesize and position
|
||||
if(result != EOF)
|
||||
{
|
||||
cb->size += 1;
|
||||
cb->size = filelength(fileno(cb->fp));
|
||||
cb->raw_position += 1;
|
||||
}
|
||||
|
||||
#if defined(CHECK_SIZE) && !defined(NDEBUG)
|
||||
Assert( cb->size == filelength(fileno(cb->fp)) );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1521,7 +1447,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;
|
||||
@@ -1548,14 +1474,10 @@ int cfputs(const char *str, CFILE *cfile)
|
||||
//WMC - update filesize and position
|
||||
if(result != EOF)
|
||||
{
|
||||
cb->size += strlen(str);
|
||||
cb->size = filelength(fileno(cb->fp));
|
||||
cb->raw_position += strlen(str);
|
||||
}
|
||||
|
||||
#if defined(CHECK_SIZE) && !defined(NDEBUG)
|
||||
Assert( cb->size == filelength(fileno(cb->fp)) );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1626,7 +1548,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 +1585,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 +1606,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 +1661,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 +1698,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 +1729,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 +1779,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;
|
||||
|
||||
+31
-102
@@ -16,9 +16,6 @@
|
||||
#include <time.h>
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#define CF_EOF (-1)
|
||||
|
||||
#define CF_SEEK_SET (0)
|
||||
@@ -99,23 +96,18 @@ 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);
|
||||
|
||||
// extra check for child directory under CF_TYPE_*
|
||||
// NOTE: if specified cf_get_file_list() will not search pack files!
|
||||
// NOTE: specified string must not contain ':' or spaces or begin with DIR_SEPARATOR!
|
||||
extern const char *Get_file_list_child;
|
||||
extern int (*Get_file_list_filter)(char *filename);
|
||||
|
||||
// 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 +115,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);
|
||||
@@ -148,27 +135,22 @@ int cflush(CFILE *cfile);
|
||||
// open a file. Once set, you can use minimum version numbers with the read functions.
|
||||
void cf_set_version( CFILE * cfile, int version );
|
||||
|
||||
// will throw an error if cfread*() functions read past this mark
|
||||
// converted to raw offsets when used, but gets passed actual length from current position
|
||||
// setting 'len' to zero will disable the check
|
||||
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();
|
||||
@@ -186,7 +168,7 @@ int cfilelength(CFILE *fp);
|
||||
int cfread(void *buf, int elsize, int nelem, CFILE *fp);
|
||||
|
||||
// cfwrite() writes to the file
|
||||
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
int cfwrite(void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
|
||||
// Reads/writes RLE compressed data.
|
||||
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
@@ -202,7 +184,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 +199,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 +225,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
|
||||
@@ -276,15 +258,8 @@ void cfread_angles(angles *ang, CFILE *file, int ver = 0, angles *deflt = NULL);
|
||||
// Reads variable length, null-termined string. Will only read up
|
||||
// to n characters.
|
||||
void cfread_string(char *buf,int n, CFILE *file);
|
||||
/**
|
||||
* @brief Read a fixed length string that is not null-terminated, with the length stored in file
|
||||
*
|
||||
* @param buf Pre-allocated array to store string
|
||||
* @param n Size of pre-allocated array
|
||||
* @param file File to read from
|
||||
*
|
||||
* @note Appends NULL character to string (buf)
|
||||
*/
|
||||
// Read a fixed length that is null-terminatedm, and has the length
|
||||
// stored in file
|
||||
void cfread_string_len(char *buf,int n, CFILE *file);
|
||||
|
||||
// functions for writing cfiles
|
||||
@@ -299,21 +274,15 @@ 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
|
||||
*
|
||||
* @param buf String to write to file
|
||||
* @param file File to write to
|
||||
*/
|
||||
int cfwrite_string_len(const char *buf, CFILE *file);
|
||||
// write a fixed length that is null-terminatedm, and has the length
|
||||
// stored in file
|
||||
int cfwrite_string_len(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( 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 );
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files.
|
||||
@@ -324,7 +293,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 +307,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);
|
||||
@@ -353,45 +322,5 @@ int cfile_push_chdir(int type);
|
||||
// restore directory on top of the stack
|
||||
int cfile_pop_dir();
|
||||
|
||||
namespace cfile
|
||||
{
|
||||
// exceptions and other errors
|
||||
class cfile_error : public std::exception
|
||||
{
|
||||
public:
|
||||
cfile_error() : m_excuse("CFILE Exception")
|
||||
{
|
||||
}
|
||||
|
||||
cfile_error(const std::string &excuse) : m_excuse(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
~cfile_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char *what() const throw()
|
||||
{
|
||||
return m_excuse.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_excuse;
|
||||
};
|
||||
|
||||
class max_read_length : public cfile_error
|
||||
{
|
||||
public:
|
||||
max_read_length(const std::string &excuse) : cfile_error(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
max_read_length() : cfile_error("Attempted to read beyond length limit")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* __CFILE_H__ */
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "cfile/cfilearchive.h"
|
||||
#include "luaconf.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
#define CHECK_POSITION
|
||||
|
||||
@@ -207,15 +205,6 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
//mprintf(( "CFILE: EOF encountered in file\n" ));
|
||||
}
|
||||
|
||||
if (cb->max_read_len) {
|
||||
if ( (size_t)(cb->raw_position+size) > cb->max_read_len ) {
|
||||
std::ostringstream s_buf;
|
||||
s_buf << "Attempted to read " << size << "-byte(s) beyond length limit";
|
||||
|
||||
throw cfile::max_read_length(s_buf.str());
|
||||
}
|
||||
}
|
||||
|
||||
int bytes_read = fread( buf, 1, size, cb->fp );
|
||||
if ( bytes_read > 0 ) {
|
||||
cb->raw_position += bytes_read;
|
||||
|
||||
@@ -37,15 +37,12 @@ typedef struct Cfile_block {
|
||||
int lib_offset;
|
||||
int raw_position;
|
||||
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 );
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
@@ -22,88 +20,11 @@
|
||||
#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 )
|
||||
{
|
||||
// NOTE: This really needs to be updated to C++ style sorting at some point
|
||||
|
||||
int i, j, incr;
|
||||
SCP_string t;
|
||||
file_list_info tt;
|
||||
|
||||
int n = (int)list.size();
|
||||
|
||||
if (sort == CF_SORT_NAME) {
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if (stricmp(list[j].c_str(), list[j + incr].c_str()) > 0) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
if (info) {
|
||||
tt = (*info)[j];
|
||||
(*info)[j] = (*info)[j + incr];
|
||||
(*info)[j + incr] = tt;
|
||||
}
|
||||
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_TIME) {
|
||||
Assert(info);
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if ( (*info)[j].write_time < (*info)[j + incr].write_time ) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
tt = (*info)[j];
|
||||
(*info)[j] = (*info)[j + incr];
|
||||
(*info)[j + incr] = tt;
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_REVERSE) {
|
||||
std::reverse( list.begin(), list.end() );
|
||||
|
||||
if (info) {
|
||||
std::reverse( info->begin(), info->end() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
|
||||
}
|
||||
|
||||
// Sorts a list of filenames using the specified sorting method (CF_SORT_*).
|
||||
// n = number of filenames in list to sort
|
||||
|
||||
+218
-507
File diff suppressed because it is too large.
Load diff
@@ -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);
|
||||
|
||||
|
||||
#endif //_CFILESYSTEM_H
|
||||
@@ -140,7 +140,7 @@ void pack_file( char *filespec, char *filename, int filesize, _fs_time_t time_wr
|
||||
}
|
||||
|
||||
memset( path, 0, sizeof(path) );
|
||||
strcpy_s( path, filename );
|
||||
strcpy( path, filename );
|
||||
|
||||
fswrite_int( (int*)&Total_size, fp_out_hdr );
|
||||
fswrite_int( &filesize, fp_out_hdr );
|
||||
@@ -186,7 +186,7 @@ void add_directory( char * dirname)
|
||||
char *tmpptr;
|
||||
int i = 0;
|
||||
|
||||
strcpy_s(path, dirname);
|
||||
strcpy(path, dirname);
|
||||
|
||||
fswrite_int( (int*)&Total_size, fp_out_hdr);
|
||||
fswrite_int( &i, fp_out_hdr);
|
||||
@@ -217,7 +217,7 @@ void pack_directory( char * filespec)
|
||||
while ( (*ts == DIR_SEPARATOR_CHAR) && (ts > filespec) )
|
||||
*ts = '\0';
|
||||
|
||||
strcpy_s( tmp1, filespec );
|
||||
strcpy( tmp1, filespec );
|
||||
|
||||
add_directory(filespec);
|
||||
strcat( tmp1, DIR_SEPARATOR_STR"*.*" );
|
||||
@@ -229,7 +229,7 @@ void pack_directory( char * filespec)
|
||||
if( find_handle != -1 ) {
|
||||
if ( find.attrib & _A_SUBDIR ) {
|
||||
if (strcmp( "..", find.name) && strcmp( ".", find.name) && strcmp( ".svn", find.name)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcpy( tmp, filespec );
|
||||
strcat( tmp, "\\" );
|
||||
strcat( tmp, find.name );
|
||||
pack_directory(tmp);
|
||||
@@ -241,7 +241,7 @@ void pack_directory( char * filespec)
|
||||
while( !_findnext( find_handle, &find ) ) {
|
||||
if ( find.attrib & _A_SUBDIR ) {
|
||||
if (strcmp( "..", find.name) && strcmp( ".", find.name) && strcmp( ".svn", find.name)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcpy( tmp, filespec );
|
||||
strcat( tmp, "\\" );
|
||||
strcat( tmp, find.name );
|
||||
pack_directory(tmp);
|
||||
@@ -278,7 +278,7 @@ void pack_directory( char * filespec)
|
||||
}
|
||||
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcpy( tmp, filespec );
|
||||
strcat( tmp, "/" );
|
||||
strcat( tmp, dir->d_name );
|
||||
pack_directory(tmp);
|
||||
@@ -340,7 +340,7 @@ void print_instructions()
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redefine main() which is something
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redfine main() which is something
|
||||
// that we don't want since we don't actually link against SDL, this solves the problem...
|
||||
#ifdef main
|
||||
#undef main
|
||||
@@ -364,14 +364,14 @@ int main(int argc, char *argv[] )
|
||||
#endif
|
||||
}
|
||||
|
||||
strcpy_s( archive, argv[1] );
|
||||
strcpy( archive, argv[1] );
|
||||
p = strchr( archive, '.' );
|
||||
if (p) *p = 0; // remove extension
|
||||
|
||||
strcpy_s( archive_dat, archive );
|
||||
strcpy( archive_dat, archive );
|
||||
strcat( archive_dat, ".vp" );
|
||||
|
||||
strcpy_s( archive_hdr, archive );
|
||||
strcpy( archive_hdr, archive );
|
||||
strcat( archive_hdr, ".hdr" );
|
||||
|
||||
fp_out = fopen( archive_dat, "wb" );
|
||||
|
||||
@@ -97,7 +97,7 @@ typedef struct vp_fileinfo {
|
||||
~vp_fileinfo() {}
|
||||
} vp_fileinfo;
|
||||
|
||||
SCP_vector<vp_fileinfo> VP_FileInfo;
|
||||
std::vector<vp_fileinfo> VP_FileInfo;
|
||||
|
||||
// just like strlwr() but without actually including it here
|
||||
void lowercase(char *s)
|
||||
@@ -224,7 +224,7 @@ void read_index(int lc = 0)
|
||||
if (lc == 1)
|
||||
lowercase( vpinfo.file_name );
|
||||
|
||||
strcpy_s( vpinfo.file_path, path );
|
||||
strcpy( vpinfo.file_path, path );
|
||||
VP_FileInfo.push_back(vpinfo);
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,7 @@ void extract_all_files(char *file)
|
||||
|
||||
printf("Extracting: %s...\n", file);
|
||||
|
||||
for (size_t i = 0; i < VP_FileInfo.size(); i++) {
|
||||
for (uint i = 0; i < VP_FileInfo.size(); i++) {
|
||||
// save the file path to a temp location and recursively make the needed directories
|
||||
if (have_outdir) {
|
||||
if ( (out_len + 1 + strlen(path)) > MAX_PATH-1 )
|
||||
@@ -311,7 +311,7 @@ void extract_all_files(char *file)
|
||||
|
||||
sprintf(path2, "%s%s%s", out_dir, DIR_SEPARATOR_STR, path);
|
||||
} else {
|
||||
strcpy_s(path2, path);
|
||||
strcpy(path2, path);
|
||||
}
|
||||
|
||||
fp_out = fopen(path2, "wb");
|
||||
@@ -365,7 +365,7 @@ void list_all_files(char *file)
|
||||
|
||||
printf(" Name Size Offset Date/Time Path\n");
|
||||
printf("-------------------------------------------------------------------------------\n");
|
||||
for (size_t i = 0; i < VP_FileInfo.size(); i++) {
|
||||
for (uint i = 0; i < VP_FileInfo.size(); i++) {
|
||||
plat_time = VP_FileInfo[i].write_time; // gets rid of some platform strangeness this way
|
||||
strftime(out_time, 32, "%F %H:%M", localtime(&plat_time)); // YYYY-mm-dd HH:mm (ISO 8601 date format, 24-hr time)
|
||||
|
||||
@@ -422,7 +422,7 @@ void help()
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redefine main() which is something
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redfine main() which is something
|
||||
// that we don't want since we don't actually link against SDL, this solves the problem...
|
||||
#ifdef main
|
||||
#undef main
|
||||
|
||||
+556
-981
File diff suppressed because it is too large.
Load diff
+19
-32
@@ -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.
|
||||
@@ -40,6 +41,7 @@ extern int Cmdline_multi_log;
|
||||
extern int Cmdline_multi_stream_chat_to_file;
|
||||
extern int Cmdline_network_port;
|
||||
extern int Cmdline_restricted_game;
|
||||
extern int Cmdline_server_firing;
|
||||
extern int Cmdline_spew_pof_info;
|
||||
extern int Cmdline_start_netgame;
|
||||
extern int Cmdline_timeout;
|
||||
@@ -47,7 +49,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 -------------------------------------------------
|
||||
@@ -61,7 +62,10 @@ extern float static_light_factor;
|
||||
extern float static_point_factor;
|
||||
extern float static_tube_factor;
|
||||
extern int Cmdline_ambient_factor;
|
||||
extern int Cmdline_cell;
|
||||
extern int Cmdline_decals;
|
||||
extern int Cmdline_env;
|
||||
extern int Cmdline_mipmap;
|
||||
extern int Cmdline_missile_lighting;
|
||||
extern int Cmdline_glow;
|
||||
extern int Cmdline_nomotiondebris;
|
||||
@@ -70,18 +74,12 @@ extern int Cmdline_spec;
|
||||
extern int Cmdline_normal;
|
||||
extern int Cmdline_height;
|
||||
extern int Cmdline_enable_3d_shockwave;
|
||||
extern int Cmdline_softparticles;
|
||||
extern int Cmdline_postprocess;
|
||||
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_d3d_lesstmem;
|
||||
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_safeloading;
|
||||
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_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_timerbar;
|
||||
extern int Cmdline_save_render_targets;
|
||||
extern int Cmdline_debug_window;
|
||||
extern int Cmdline_verify_vps;
|
||||
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;
|
||||
#ifdef SCP_UNIX
|
||||
extern int Cmdline_no_grab;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//extern char FreeSpace_Directory[]; // allievating a cfilesystem problem caused by fred -- Kazan
|
||||
#endif
|
||||
+201
-17
@@ -10,18 +10,202 @@
|
||||
|
||||
|
||||
#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 "freespace2/freespace.h"
|
||||
//#include "model/model.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"
|
||||
|
||||
|
||||
//cmeasure_info Cmeasure_info[MAX_CMEASURE_TYPES];
|
||||
//cmeasure Cmeasures[MAX_CMEASURES];
|
||||
|
||||
//int Num_cmeasure_types = 0;
|
||||
//int Num_cmeasures = 0;
|
||||
//int Cmeasure_inited = 0;
|
||||
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;
|
||||
|
||||
// This will get called at the start of each level.
|
||||
//Not anymore - WMC
|
||||
/*
|
||||
void cmeasure_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !Cmeasure_inited )
|
||||
Cmeasure_inited = 1;
|
||||
|
||||
// Reset everything between levels
|
||||
Num_cmeasures = 0;
|
||||
|
||||
for (i=0; i<MAX_CMEASURES; i++ ) {
|
||||
Cmeasures[i].subtype = CMEASURE_UNUSED;
|
||||
}
|
||||
|
||||
}*/
|
||||
/*
|
||||
void cmeasure_render(object * objp)
|
||||
{
|
||||
// JAS TODO: Replace with proper fireball
|
||||
cmeasure *cmp;
|
||||
cmeasure_info *cmip;
|
||||
|
||||
cmp = &Cmeasures[objp->instance];
|
||||
cmip = &Cmeasure_info[cmp->subtype];
|
||||
|
||||
if ( cmp->subtype == CMEASURE_UNUSED ) {
|
||||
Int3(); // Hey, what are we doing in here?
|
||||
return;
|
||||
}
|
||||
|
||||
if ( cmip->model_num > -1 ) {
|
||||
model_clear_instance(cmip->model_num);
|
||||
model_render(cmip->model_num, &objp->orient, &objp->pos, MR_NO_LIGHTING );
|
||||
} else {
|
||||
mprintf(( "Not rendering countermeasure because model_num is negative\n" ));
|
||||
}
|
||||
}*/
|
||||
/*
|
||||
void cmeasure_delete( object * objp )
|
||||
{
|
||||
int num;
|
||||
|
||||
num = objp->instance;
|
||||
|
||||
// Assert( Cmeasures[num].objnum == OBJ_INDEX(objp));
|
||||
|
||||
Cmeasures[num].subtype = CMEASURE_UNUSED;
|
||||
Num_cmeasures--;
|
||||
Assert( Num_cmeasures >= 0 );
|
||||
}*/
|
||||
|
||||
// broke cmeasure_move into two functions -- process_pre and process_post (as was done with
|
||||
// all *_move functions). Nothing to do for process_pre
|
||||
/*
|
||||
void cmeasure_process_pre( object *objp, float frame_time)
|
||||
{
|
||||
}*/
|
||||
/*
|
||||
void cmeasure_process_post(object * objp, float frame_time)
|
||||
{
|
||||
int num;
|
||||
num = objp->instance;
|
||||
|
||||
// Assert( Cmeasures[num].objnum == objnum );
|
||||
cmeasure *cmp = &Cmeasures[num];
|
||||
|
||||
if ( cmp->lifeleft >= 0.0f) {
|
||||
cmp->lifeleft -= frame_time;
|
||||
if ( cmp->lifeleft < 0.0f ) {
|
||||
objp->flags |= OF_SHOULD_BE_DEAD;
|
||||
// demo_do_flag_dead(OBJ_INDEX(objp));
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
// creates one countermeasure. A ship fires 1 of these per launch. rand_val is used
|
||||
// in multiplayer. If -1, then create a random number. If non-negative, use this
|
||||
// number for static_rand functions
|
||||
/*
|
||||
int cmeasure_create( object * source_obj, vec3d * pos, int cm_type, int rand_val )
|
||||
{
|
||||
int n, objnum, parent_objnum, arand;
|
||||
object * obj;
|
||||
ship *shipp;
|
||||
cmeasure *cmp;
|
||||
cmeasure_info *cmeasurep;
|
||||
|
||||
Cmeasures_homing_check = 2; // Tell homing code to scan everything for two frames. If only one frame, get sync problems due to objects being created at end of frame!
|
||||
|
||||
parent_objnum = OBJ_INDEX(source_obj);
|
||||
|
||||
Assert( source_obj->type == OBJ_SHIP );
|
||||
Assert( source_obj->instance >= 0 && source_obj->instance < MAX_SHIPS );
|
||||
|
||||
shipp = &Ships[source_obj->instance];
|
||||
|
||||
if ( Num_cmeasures >= MAX_CMEASURES)
|
||||
return -1;
|
||||
|
||||
for (n=0; n<MAX_CMEASURES; n++ )
|
||||
if ( Cmeasures[n].subtype == CMEASURE_UNUSED)
|
||||
break;
|
||||
if ( n == MAX_CMEASURES)
|
||||
return -1;
|
||||
|
||||
nprintf(("Network", "Cmeasure created by %s\n", Ships[source_obj->instance].ship_name));
|
||||
|
||||
cmp = &Cmeasures[n];
|
||||
cmeasurep = &Cmeasure_info[cm_type];
|
||||
|
||||
if ( pos == NULL )
|
||||
pos = &source_obj->pos;
|
||||
|
||||
objnum = obj_create( OBJ_CMEASURE, parent_objnum, n, &source_obj->orient, pos, 1.0f, OF_RENDERS | OF_PHYSICS );
|
||||
|
||||
Assert( objnum >= 0 && objnum < MAX_OBJECTS );
|
||||
|
||||
// Create Debris piece n!
|
||||
if ( rand_val == -1 )
|
||||
arand = myrand(); // use a random number to get lifeleft, and random vector for displacement from ship
|
||||
else
|
||||
arand = rand_val;
|
||||
|
||||
cmp->lifeleft = static_randf(arand) * (cmeasurep->life_max - cmeasurep->life_min) / cmeasurep->life_min;
|
||||
if (source_obj->flags & OF_PLAYER_SHIP){
|
||||
cmp->lifeleft *= The_mission.ai_profile->cmeasure_life_scale[Game_skill_level];
|
||||
}
|
||||
cmp->lifeleft = cmeasurep->life_min + cmp->lifeleft * (cmeasurep->life_max - cmeasurep->life_min);
|
||||
|
||||
// cmp->objnum = objnum;
|
||||
cmp->team = shipp->team;
|
||||
cmp->subtype = cm_type;
|
||||
cmp->objnum = objnum;
|
||||
cmp->source_objnum = parent_objnum;
|
||||
cmp->source_sig = Objects[objnum].signature;
|
||||
|
||||
cmp->flags = 0;
|
||||
|
||||
nprintf(("Jim", "Frame %i: Launching countermeasure #%i\n", Framecount, Objects[objnum].signature));
|
||||
|
||||
obj = &Objects[objnum];
|
||||
|
||||
Num_cmeasures++;
|
||||
|
||||
//Set countermeasure velocity
|
||||
vec3d vel, rand_vec;
|
||||
|
||||
//Get cmeasure rear velocity in world
|
||||
vm_vec_scale_add(&vel, &source_obj->phys_info.vel, &source_obj->orient.vec.fvec, -25.0f);
|
||||
|
||||
//Get random velocity vector
|
||||
static_randvec(arand+1, &rand_vec);
|
||||
|
||||
//Add it to the rear velocity
|
||||
vm_vec_scale_add2(&vel, &rand_vec, 2.0f);
|
||||
|
||||
obj->phys_info.vel = vel;
|
||||
|
||||
vm_vec_zero(&obj->phys_info.rotvel);
|
||||
vm_vec_zero(&obj->phys_info.max_vel);
|
||||
vm_vec_zero(&obj->phys_info.max_rotvel);
|
||||
|
||||
// blow out his reverse thrusters. Or drag, same thing.
|
||||
obj->phys_info.rotdamp = 10000.0f;
|
||||
obj->phys_info.side_slip_time_const = 10000.0f;
|
||||
|
||||
obj->phys_info.max_vel.xyz.z = -25.0f;
|
||||
vm_vec_copy_scale(&obj->phys_info.desired_vel, &obj->orient.vec.fvec, obj->phys_info.max_vel.xyz.z );
|
||||
|
||||
return arand; // need to return this value for multiplayer purposes
|
||||
}*/
|
||||
|
||||
//Used to set a countermeasure velocity after being launched from a ship as a countermeasure
|
||||
//ie not as a primary or secondary.
|
||||
@@ -45,6 +229,12 @@ void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand)
|
||||
vm_vec_zero(&objp->phys_info.max_vel);
|
||||
vm_vec_zero(&objp->phys_info.max_rotvel);
|
||||
|
||||
//Idunnit. -WMC
|
||||
//objp->phys_info.flags |= PF_CONST_VEL;
|
||||
|
||||
//WMC - I don't think this stuff is needed with the flag I set
|
||||
//WMC - Or maybe it is.
|
||||
|
||||
// blow out his reverse thrusters. Or drag, same thing.
|
||||
objp->phys_info.rotdamp = 10000.0f;
|
||||
objp->phys_info.side_slip_time_const = 10000.0f;
|
||||
@@ -69,18 +259,12 @@ void cmeasure_select_next(ship *shipp)
|
||||
}
|
||||
}
|
||||
|
||||
//snd_play( &Snds[SND_CMEASURE_CYCLE] );
|
||||
|
||||
mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief If this is a player countermeasure, let the player know they evaded a missile.
|
||||
* @param objp [description]
|
||||
*
|
||||
* During single player games, this function notifies the player that evasion has occurred.
|
||||
* Multiplayer games ensure that #send_countermeasure_success_packet() is called to notify the other player.
|
||||
*/
|
||||
|
||||
// If this is a player countermeasure, let the player know he evaded a missile
|
||||
void cmeasure_maybe_alert_success(object *objp)
|
||||
{
|
||||
//Is this a countermeasure, and does it have a parent
|
||||
@@ -92,7 +276,7 @@ void cmeasure_maybe_alert_success(object *objp)
|
||||
|
||||
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
|
||||
hud_start_text_flash(XSTR("Evaded", 1430), 800);
|
||||
snd_play(&Snds[ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)]);
|
||||
snd_play(&Snds[SND_MISSILE_EVADED_POPUP]);
|
||||
} else if ( Objects[objp->parent].flags & OF_PLAYER_SHIP ) {
|
||||
send_countermeasure_success_packet( objp->parent );
|
||||
}
|
||||
|
||||
@@ -15,20 +15,64 @@
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
|
||||
class object;
|
||||
struct object;
|
||||
//struct vec3d;
|
||||
|
||||
//#define MAX_CMEASURES 64
|
||||
|
||||
// Goes in cmeasure.subtype
|
||||
//#define CMEASURE_UNUSED -1
|
||||
|
||||
//#define MAX_CMEASURE_TYPES 3
|
||||
|
||||
#define CMEASURE_WAIT 333 // delay in milliseconds between countermeasure firing.
|
||||
|
||||
//#define CMF_DUD_HEAT 0x01 // If set, this cmeasure is a dud to heat seekers. Set at create time.
|
||||
//#define CMF_DUD_ASPECT 0x02 // If set, this cmeasure is a dud to aspect seekers. Set at create time.
|
||||
|
||||
//#define CMF_DUD (CMF_DUD_HEAT | CMF_DUD_ASPECT)
|
||||
|
||||
// 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;
|
||||
/*
|
||||
typedef struct cmeasure_info {
|
||||
char cmeasure_name[NAME_LENGTH];
|
||||
//float max_speed; // launch speed, relative to ship
|
||||
float fire_wait; // time between launches
|
||||
float life_min, life_max; // lifetime will be in range min..max.
|
||||
int launch_sound; // Sound played when launched.
|
||||
char pof_name[NAME_LENGTH];
|
||||
int model_num; // What this renders as
|
||||
} cmeasure_info;
|
||||
|
||||
typedef struct cmeasure {
|
||||
int flags; // You know, flag type things.
|
||||
int subtype; // See CMEASURE_??? defines
|
||||
int objnum;
|
||||
int source_objnum; // What object this came from
|
||||
int source_sig; // Signature of the source object
|
||||
int team; // Team of the ship where the cmeasure came from
|
||||
float lifeleft; // When 0 or less object dies
|
||||
} cmeasure;
|
||||
*/
|
||||
//extern cmeasure_info Cmeasure_info[MAX_CMEASURE_TYPES];
|
||||
//extern cmeasure Cmeasures[MAX_CMEASURES];
|
||||
//extern int Num_cmeasure_types;
|
||||
//extern int Num_cmeasures;
|
||||
extern int Cmeasures_homing_check;
|
||||
extern int Countermeasures_enabled;
|
||||
|
||||
//extern void cmeasure_init();
|
||||
//extern void cmeasure_render( object * obj );
|
||||
//extern void cmeasure_delete( object * obj );
|
||||
//extern void cmeasure_process_pre( object * obj, float frame_time);
|
||||
//extern void cmeasure_process_post( object * obj, float frame_time);
|
||||
//extern int cmeasure_create( object * source_obj, vec3d *pos, int cm_type, int rand_val = -1 );
|
||||
extern void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand);
|
||||
extern void cmeasure_select_next(object *objp);
|
||||
extern void cmeasure_maybe_alert_success(object *objp);
|
||||
|
||||
extern float Skill_level_cmeasure_life_scale[NUM_SKILL_LEVELS];
|
||||
|
||||
#endif // _CMEASURE_H
|
||||
File diff suppressed because it is too large.
Load diff
+174
-240
@@ -5,276 +5,214 @@
|
||||
* 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 {
|
||||
TARGET_NEXT =0, //!< target next
|
||||
TARGET_PREV =1, //!< target previous
|
||||
TARGET_NEXT_CLOSEST_HOSTILE =2, //!< target the next hostile target
|
||||
TARGET_PREV_CLOSEST_HOSTILE =3, //!< target the previous closest hostile
|
||||
TOGGLE_AUTO_TARGETING =4, //!< toggle auto-targeting
|
||||
TARGET_NEXT_CLOSEST_FRIENDLY =5, //!< target the next friendly ship
|
||||
TARGET_PREV_CLOSEST_FRIENDLY =6, //!< target the closest friendly ship
|
||||
TARGET_SHIP_IN_RETICLE =7, //!< target ship closest to center of reticle
|
||||
TARGET_CLOSEST_SHIP_ATTACKING_TARGET =8, //!< target the closest ship attacking current target
|
||||
TARGET_LAST_TRANMISSION_SENDER =9, //!< TARGET_LAST_TRANMISSION_SENDER
|
||||
STOP_TARGETING_SHIP =10, //!< stop targeting ship
|
||||
// --------------------------------------------------
|
||||
// Keyboard #defines for the actions
|
||||
// This is the value of the id field in config_item
|
||||
// --------------------------------------------------
|
||||
|
||||
//!< @n
|
||||
//!< 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
|
||||
// targeting a ship
|
||||
|
||||
//!< @n
|
||||
//!< Speed Matching
|
||||
//!< ----------------
|
||||
MATCH_TARGET_SPEED =15, //!< match target speed
|
||||
TOGGLE_AUTO_MATCH_TARGET_SPEED =16, //!< toggle auto-match target speed
|
||||
#define TARGET_NEXT 0
|
||||
#define TARGET_PREV 1
|
||||
#define TARGET_NEXT_CLOSEST_HOSTILE 2
|
||||
#define TARGET_PREV_CLOSEST_HOSTILE 3
|
||||
#define TOGGLE_AUTO_TARGETING 4
|
||||
#define TARGET_NEXT_CLOSEST_FRIENDLY 5
|
||||
#define TARGET_PREV_CLOSEST_FRIENDLY 6
|
||||
#define TARGET_SHIP_IN_RETICLE 7
|
||||
#define TARGET_CLOSEST_SHIP_ATTACKING_TARGET 8
|
||||
#define TARGET_LAST_TRANMISSION_SENDER 9
|
||||
#define STOP_TARGETING_SHIP 10
|
||||
|
||||
//!< @n
|
||||
//!< Weapons
|
||||
//!< ---------
|
||||
FIRE_PRIMARY =17, //!< FIRE_PRIMARY
|
||||
FIRE_SECONDARY =18, //!< FIRE_SECONDARY
|
||||
CYCLE_NEXT_PRIMARY =19, //!< cycle to next primary weapon
|
||||
CYCLE_PREV_PRIMARY =20, //!< cycle to previous primary weapon
|
||||
CYCLE_SECONDARY =21, //!< cycle to next secondary weapon
|
||||
CYCLE_NUM_MISSLES =22, //!< cycle number of missiles fired from secondary bank
|
||||
LAUNCH_COUNTERMEASURE =23, //!< LAUNCH_COUNTERMEASURE
|
||||
// targeting a ship's subsystem
|
||||
#define TARGET_SUBOBJECT_IN_RETICLE 11
|
||||
#define TARGET_NEXT_SUBOBJECT 12
|
||||
#define TARGET_PREV_SUBOBJECT 13
|
||||
#define STOP_TARGETING_SUBSYSTEM 14
|
||||
|
||||
//!< @n
|
||||
//!< Controls
|
||||
//!< ----------
|
||||
FORWARD_THRUST =24, //!< FORWARD_THRUST
|
||||
REVERSE_THRUST =25, //!< REVERSE_THRUST
|
||||
BANK_LEFT =26, //!< BANK_LEFT
|
||||
BANK_RIGHT =27, //!< BANK_RIGHT
|
||||
PITCH_FORWARD =28, //!< PITCH_FORWARD
|
||||
PITCH_BACK =29, //!< PITCH_BACK
|
||||
YAW_LEFT =30, //!< YAW_LEFT
|
||||
YAW_RIGHT =31, //!< YAW_RIGHT
|
||||
// speed matching
|
||||
#define MATCH_TARGET_SPEED 15
|
||||
#define TOGGLE_AUTO_MATCH_TARGET_SPEED 16
|
||||
|
||||
//!< @n
|
||||
//!< Throttle Control
|
||||
//!< ------------------
|
||||
ZERO_THROTTLE =32, //!< ZERO_THROTTLE
|
||||
MAX_THROTTLE =33, //!< MAX_THROTTLE
|
||||
ONE_THIRD_THROTTLE =34, //!< ONE_THIRD_THROTTLE
|
||||
TWO_THIRDS_THROTTLE =35, //!< TWO_THIRDS_THROTTLE
|
||||
PLUS_5_PERCENT_THROTTLE =36, //!< PLUS_5_PERCENT_THROTTLE
|
||||
MINUS_5_PERCENT_THROTTLE =37, //!< MINUS_5_PERCENT_THROTTLE
|
||||
// weapons
|
||||
#define FIRE_PRIMARY 17
|
||||
#define FIRE_SECONDARY 18
|
||||
#define CYCLE_NEXT_PRIMARY 19
|
||||
#define CYCLE_PREV_PRIMARY 20
|
||||
#define CYCLE_SECONDARY 21
|
||||
#define CYCLE_NUM_MISSLES 22
|
||||
#define LAUNCH_COUNTERMEASURE 23
|
||||
|
||||
//!< @n
|
||||
//!< 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
|
||||
ATTACK_SUBSYSTEM_MESSAGE =41, //!< wingman message: disable current target
|
||||
CAPTURE_MESSAGE =42, //!< wingman message: capture current target
|
||||
ENGAGE_MESSAGE =43, //!< wingman message: engage enemy
|
||||
FORM_MESSAGE =44, //!< wingman message: form on my wing
|
||||
IGNORE_MESSAGE =45, //!< IGNORE_MESSAGE
|
||||
PROTECT_MESSAGE =46, //!< wingman message: protect current target
|
||||
COVER_MESSAGE =47, //!< wingman message: cover me
|
||||
WARP_MESSAGE =48, //!< wingman message: warp out
|
||||
REARM_MESSAGE =49, //!< REARM_MESSAGE
|
||||
TARGET_CLOSEST_SHIP_ATTACKING_SELF =50, //!< target closest ship that is attacking player
|
||||
// controls
|
||||
#define FORWARD_THRUST 24
|
||||
#define REVERSE_THRUST 25
|
||||
#define BANK_LEFT 26
|
||||
#define BANK_RIGHT 27
|
||||
#define PITCH_FORWARD 28
|
||||
#define PITCH_BACK 29
|
||||
#define YAW_LEFT 30
|
||||
#define YAW_RIGHT 31
|
||||
|
||||
//!< @n
|
||||
//!< Views
|
||||
//!< -------
|
||||
VIEW_CHASE =51, //!< VIEW_CHASE
|
||||
VIEW_EXTERNAL =52, //!< VIEW_EXTERNAL
|
||||
VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK =53, //!< VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK
|
||||
VIEW_SLEW =54, //!< VIEW_SLEW
|
||||
VIEW_OTHER_SHIP =55, //!< VIEW_OTHER_SHIP
|
||||
VIEW_DIST_INCREASE =56, //!< VIEW_DIST_INCREASE
|
||||
VIEW_DIST_DECREASE =57, //!< VIEW_DIST_DECREASE
|
||||
VIEW_CENTER =58, //!< VIEW_CENTER
|
||||
PADLOCK_UP =59, //!< PADLOCK_UP
|
||||
PADLOCK_DOWN =60, //!< PADLOCK_DOWN
|
||||
PADLOCK_LEFT =61, //!< PADLOCK_LEFT
|
||||
PADLOCK_RIGHT =62, //!< PADLOCK_RIGHT
|
||||
// throttle control
|
||||
#define ZERO_THROTTLE 32
|
||||
#define MAX_THROTTLE 33
|
||||
#define ONE_THIRD_THROTTLE 34
|
||||
#define TWO_THIRDS_THROTTLE 35
|
||||
#define PLUS_5_PERCENT_THROTTLE 36
|
||||
#define MINUS_5_PERCENT_THROTTLE 37
|
||||
|
||||
//!< @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
|
||||
END_MISSION =66, //!< end the mission
|
||||
TARGET_TARGETS_TARGET =67, //!< target your target's target
|
||||
AFTERBURNER =68, //!< AFTERBURNER
|
||||
// squadmate messaging keys
|
||||
#define ATTACK_MESSAGE 38
|
||||
#define DISARM_MESSAGE 39
|
||||
#define DISABLE_MESSAGE 40
|
||||
#define ATTACK_SUBSYSTEM_MESSAGE 41
|
||||
#define CAPTURE_MESSAGE 42
|
||||
#define ENGAGE_MESSAGE 43
|
||||
#define FORM_MESSAGE 44
|
||||
#define IGNORE_MESSAGE 45
|
||||
#define PROTECT_MESSAGE 46
|
||||
#define COVER_MESSAGE 47
|
||||
#define WARP_MESSAGE 48
|
||||
#define REARM_MESSAGE 49
|
||||
|
||||
//!< @n
|
||||
//!< ETS
|
||||
//!< -----
|
||||
INCREASE_WEAPON =69, //!< increase weapon recharge rate
|
||||
DECREASE_WEAPON =70, //!< decrease weapon recharge rate
|
||||
INCREASE_SHIELD =71, //!< increase shield recharge rate
|
||||
DECREASE_SHIELD =72, //!< decrease shield recharge rate
|
||||
INCREASE_ENGINE =73, //!< increase energy to engines
|
||||
DECREASE_ENGINE =74, //!< decrease energy to engines
|
||||
ETS_EQUALIZE =75, //!< equalize recharge rates
|
||||
SHIELD_EQUALIZE =76, //!< equalize shield energy to all quadrants
|
||||
SHIELD_XFER_TOP =77, //!< transfer shield energy to front
|
||||
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
|
||||
#define TARGET_CLOSEST_SHIP_ATTACKING_SELF 50
|
||||
|
||||
//!< @n
|
||||
//!< Misc Controls 2
|
||||
//!< -----------------
|
||||
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
|
||||
// Views
|
||||
#define VIEW_CHASE 51
|
||||
#define VIEW_EXTERNAL 52
|
||||
#define VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK 53
|
||||
#define VIEW_SLEW 54
|
||||
#define VIEW_OTHER_SHIP 55
|
||||
#define VIEW_DIST_INCREASE 56
|
||||
#define VIEW_DIST_DECREASE 57
|
||||
#define VIEW_CENTER 58
|
||||
#define PADLOCK_UP 59
|
||||
#define PADLOCK_DOWN 60
|
||||
#define PADLOCK_LEFT 61
|
||||
#define PADLOCK_RIGHT 62
|
||||
|
||||
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
|
||||
#define RADAR_RANGE_CYCLE 63
|
||||
#define SQUADMSG_MENU 64
|
||||
#define SHOW_GOALS 65
|
||||
#define END_MISSION 66
|
||||
#define TARGET_TARGETS_TARGET 67
|
||||
#define AFTERBURNER 68
|
||||
|
||||
TARGET_NEXT_BOMB =95, //!< TARGET_NEXT_BOMB
|
||||
TARGET_PREV_BOMB =96, //!< TARGET_PREV_BOMB
|
||||
#define INCREASE_WEAPON 69
|
||||
#define DECREASE_WEAPON 70
|
||||
#define INCREASE_SHIELD 71
|
||||
#define DECREASE_SHIELD 72
|
||||
#define INCREASE_ENGINE 73
|
||||
#define DECREASE_ENGINE 74
|
||||
#define ETS_EQUALIZE 75
|
||||
#define SHIELD_EQUALIZE 76
|
||||
#define SHIELD_XFER_TOP 77
|
||||
#define SHIELD_XFER_BOTTOM 78
|
||||
#define SHIELD_XFER_LEFT 79
|
||||
#define SHIELD_XFER_RIGHT 80
|
||||
|
||||
//!< @n
|
||||
//!< 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)
|
||||
#define XFER_SHIELD 81
|
||||
#define XFER_LASER 82
|
||||
//#define SHOW_DAMAGE_POPUP 83 // AL: this binding should be removing next time the controls are reorganized
|
||||
|
||||
//!< @n
|
||||
//!< Multiplayer misc keys
|
||||
//!< -----------------------
|
||||
MULTI_OBSERVER_ZOOM_TO =101, //!< if i'm an observer, zoom to my targeted object
|
||||
#define GLIDE_WHEN_PRESSED 83
|
||||
//Backslash -- this was a convenient place for Glide When Pressed, since Show Damage Popup isn't used
|
||||
#define BANK_WHEN_PRESSED 84
|
||||
#define SHOW_NAVMAP 85
|
||||
#define ADD_REMOVE_ESCORT 86
|
||||
#define ESCORT_CLEAR 87
|
||||
#define TARGET_NEXT_ESCORT_SHIP 88
|
||||
|
||||
TIME_SPEED_UP =102, //!< TIME_SPEED_UP
|
||||
TIME_SLOW_DOWN =103, //!< TIME_SLOW_DOWN
|
||||
#define TARGET_CLOSEST_REPAIR_SHIP 89
|
||||
#define TARGET_NEXT_UNINSPECTED_CARGO 90
|
||||
#define TARGET_PREV_UNINSPECTED_CARGO 91
|
||||
#define TARGET_NEWEST_SHIP 92
|
||||
#define TARGET_NEXT_LIVE_TURRET 93
|
||||
#define TARGET_PREV_LIVE_TURRET 94
|
||||
|
||||
TOGGLE_HUD_CONTRAST =104, //!< toggle between high and low HUD contrast
|
||||
#define TARGET_NEXT_BOMB 95
|
||||
#define TARGET_PREV_BOMB 96
|
||||
|
||||
MULTI_TOGGLE_NETINFO =105, //!< toggle network info
|
||||
// multiplayer messaging keys
|
||||
#define MULTI_MESSAGE_ALL 97
|
||||
#define MULTI_MESSAGE_FRIENDLY 98
|
||||
#define MULTI_MESSAGE_HOSTILE 99
|
||||
#define MULTI_MESSAGE_TARGET 100
|
||||
|
||||
MULTI_SELF_DESTRUCT =106, //!< self destruct (multiplayer only)
|
||||
// multiplayer misc keys
|
||||
#define MULTI_OBSERVER_ZOOM_TO 101
|
||||
|
||||
//!< @n
|
||||
//!< Misc Controls 3
|
||||
//!< -----------------
|
||||
TOGGLE_HUD =107, //!< TOGGLE_HUD
|
||||
RIGHT_SLIDE_THRUST =108, //!< RIGHT_SLIDE_THRUST
|
||||
LEFT_SLIDE_THRUST =109, //!< LEFT_SLIDE_THRUST
|
||||
UP_SLIDE_THRUST =110, //!< UP_SLIDE_THRUST
|
||||
DOWN_SLIDE_THRUST =111, //!< DOWN_SLIDE_THRUST
|
||||
HUD_TARGETBOX_TOGGLE_WIREFRAME =112, //!< HUD_TARGETBOX_TOGGLE_WIREFRAME
|
||||
VIEW_TOPDOWN =113, //!< VIEW_TOPDOWN
|
||||
VIEW_TRACK_TARGET =114, //!< VIEW_TRACK_TARGET
|
||||
#define TIME_SPEED_UP 102
|
||||
#define TIME_SLOW_DOWN 103
|
||||
|
||||
//!< @n
|
||||
//!< AutoPilot - Kazan
|
||||
//!< -------------------
|
||||
AUTO_PILOT_TOGGLE =115, //!< Autopilot key control
|
||||
NAV_CYCLE =116, //!< NAV_CYCLE
|
||||
#define TOGGLE_HUD_CONTRAST 104
|
||||
|
||||
//!< @n
|
||||
//!< Gliding
|
||||
//!< ---------
|
||||
TOGGLE_GLIDING =117, //!< TOGGLE_GLIDING
|
||||
#define MULTI_TOGGLE_NETINFO 105
|
||||
|
||||
//!< @n
|
||||
//!< Additional weapon controls
|
||||
//!< ----------------------------
|
||||
CYCLE_PRIMARY_WEAPON_SEQUENCE =118, //!< cycle num primaries to fire at once
|
||||
#define MULTI_SELF_DESTRUCT 106
|
||||
|
||||
/*!
|
||||
* This must always be below the last defined item
|
||||
*/
|
||||
CCFG_MAX //!< The total number of defined control actions (or last define + 1)
|
||||
};
|
||||
#define TOGGLE_HUD 107
|
||||
#define RIGHT_SLIDE_THRUST 108
|
||||
#define LEFT_SLIDE_THRUST 109
|
||||
#define UP_SLIDE_THRUST 110
|
||||
#define DOWN_SLIDE_THRUST 111
|
||||
#define HUD_TARGETBOX_TOGGLE_WIREFRAME 112
|
||||
#define VIEW_TOPDOWN 113
|
||||
#define VIEW_TRACK_TARGET 114
|
||||
|
||||
//AutoPilot - Kazan
|
||||
#define AUTO_PILOT_TOGGLE 115
|
||||
#define NAV_CYCLE 116
|
||||
|
||||
//Gliding
|
||||
#define TOGGLE_GLIDING 117
|
||||
|
||||
// this should be the total number of control action defines above (or last define + 1)
|
||||
#define CCFG_MAX 118
|
||||
|
||||
extern int Failed_key_index;
|
||||
extern int Invert_heading;
|
||||
@@ -288,16 +226,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 +239,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);
|
||||
|
||||
@@ -7,26 +7,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
#include "controlconfig/controlsconfig.h"
|
||||
#include "globalincs/def_files.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "io/joy.h"
|
||||
#include "io/key.h"
|
||||
#include "io/joy.h"
|
||||
#include "localization/localize.h"
|
||||
#include "parse/parselo.h"
|
||||
|
||||
// z64: These enumerations MUST equal to those in controlsconfig.cpp...
|
||||
// z64: Really need a better way than this.
|
||||
enum CC_tab {
|
||||
TARGET_TAB =0,
|
||||
SHIP_TAB =1,
|
||||
WEAPON_TAB =2,
|
||||
COMPUTER_TAB =3
|
||||
};
|
||||
|
||||
#define TARGET_TAB 0
|
||||
#define SHIP_TAB 1
|
||||
#define WEAPON_TAB 2
|
||||
#define COMPUTER_TAB 3
|
||||
|
||||
int Failed_key_index;
|
||||
|
||||
@@ -40,169 +32,168 @@ int Axis_enabled_defaults[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
|
||||
int Invert_axis[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
|
||||
int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
//! arrays which hold the key mappings. The array index represents a key-independent action.
|
||||
//! please use SPACES for aligning the fields of this array
|
||||
// arrays which hold the key mappings. The array index represents a key-independent action.
|
||||
//
|
||||
//XSTR:OFF
|
||||
config_item Control_config[CCFG_MAX + 1] = {
|
||||
// targeting a ship
|
||||
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship" },
|
||||
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship" },
|
||||
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship" },
|
||||
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship" },
|
||||
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting" },
|
||||
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship" },
|
||||
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship" },
|
||||
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle" },
|
||||
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker" },
|
||||
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission" },
|
||||
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting" },
|
||||
|
||||
// targeting a ship's subsystem
|
||||
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle" },
|
||||
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem" },
|
||||
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem" },
|
||||
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems" },
|
||||
|
||||
// matching speed
|
||||
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed" },
|
||||
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching" },
|
||||
|
||||
// weapons
|
||||
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon" },
|
||||
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon" },
|
||||
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank" },
|
||||
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate" },
|
||||
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure" },
|
||||
|
||||
// controls
|
||||
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS },
|
||||
|
||||
// throttle controls
|
||||
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero" },
|
||||
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max" },
|
||||
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third" },
|
||||
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds" },
|
||||
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent" },
|
||||
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent" },
|
||||
|
||||
// squadmate messaging
|
||||
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target" },
|
||||
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target" },
|
||||
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target" },
|
||||
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem" },
|
||||
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target" },
|
||||
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy" },
|
||||
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing" },
|
||||
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target" },
|
||||
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target" },
|
||||
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me" },
|
||||
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base" },
|
||||
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me" },
|
||||
|
||||
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship" },
|
||||
|
||||
// Views
|
||||
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false }, // Not in use anymore (Swifty)
|
||||
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View" },
|
||||
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View"},
|
||||
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock"},
|
||||
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS }, // Not in use anymore (Swifty)
|
||||
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View" },
|
||||
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS },
|
||||
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS },
|
||||
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS },
|
||||
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS },
|
||||
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS },
|
||||
|
||||
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range" },
|
||||
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu" },
|
||||
{ -1, -1, -1, true, "Show Objectives" },
|
||||
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)" },
|
||||
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target" },
|
||||
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS },
|
||||
|
||||
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy" },
|
||||
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy" },
|
||||
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy" },
|
||||
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy" },
|
||||
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy" },
|
||||
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy" },
|
||||
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings" },
|
||||
|
||||
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
// { -1, -1, -1, true, "Show Damage Popup Window" },
|
||||
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields" },
|
||||
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield" },
|
||||
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield" },
|
||||
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield" },
|
||||
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield" },
|
||||
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield" },
|
||||
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser" },
|
||||
// { -1, -1, -1, true, "Show Damage Popup Window" },
|
||||
|
||||
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS },
|
||||
//Backslash -- this was a convenient place for Glide When Pressed, as Show Damage Popup isn't used
|
||||
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS },
|
||||
{ -1, -1, -1, true, "Show Nav Map" },
|
||||
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort" },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List" },
|
||||
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship" },
|
||||
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship" },
|
||||
|
||||
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo" },
|
||||
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo" },
|
||||
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area" },
|
||||
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret" },
|
||||
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret" },
|
||||
|
||||
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber" },
|
||||
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber" },
|
||||
|
||||
// multiplayer messaging keys
|
||||
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_CONTINUOUS },
|
||||
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target"},
|
||||
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression" },
|
||||
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression" },
|
||||
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast" },
|
||||
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info"},
|
||||
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct"},
|
||||
|
||||
// Misc
|
||||
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false }, // (Swifty) Toggle for VM_TRACK
|
||||
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD"},
|
||||
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS},
|
||||
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS},
|
||||
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS},
|
||||
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS},
|
||||
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View"},
|
||||
{ -1, -1, COMPUTER_TAB, false, "Top-Down View"},
|
||||
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View"}, // (Swifty) Toggle for VM_TRACK
|
||||
// Auto Navigation Systen
|
||||
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
|
||||
{ -1, -1, -1, false, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
|
||||
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot"},
|
||||
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points"},
|
||||
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding"},
|
||||
{ -1, -1, -1, false, "" }
|
||||
};
|
||||
|
||||
char *Scan_code_text_german[] = {
|
||||
"", "Esc", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab",
|
||||
"7", "8", "9", "0", "Akzent '", "\xE1", "R\x81""cktaste", "Tab",
|
||||
"Q", "W", "E", "R", "T", "Z", "U", "I",
|
||||
"O", "P", "\x9A", "+", "Eingabe", "Strg Links", "A", "S",
|
||||
|
||||
"D", "F", "G", "H", "J", "K", "L", "\x99",
|
||||
"\x8E", "`", "Shift", "#", "Y", "X", "C", "V",
|
||||
"\xAE", "`", "Shift", "#", "Y", "X", "C", "V",
|
||||
"B", "N", "M", ",", ".", "-", "Shift", "Num *",
|
||||
"Alt", "Leertaste", "Hochstell", "F1", "F2", "F3", "F4", "F5",
|
||||
|
||||
@@ -294,61 +285,10 @@ char *Joy_button_text_french[] = {
|
||||
"Bouton 13", "Bouton 14", "Bouton 15", "Bouton 16", "Bouton 17", "Bouton 18",
|
||||
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
|
||||
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
|
||||
"Bouton 31", "Bouton 32", "Chapeau Arri\x8Are", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
"Bouton 31", "Bouton 32", "Chapeau Arrière", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
};
|
||||
|
||||
char *Scan_code_text_polish[] = {
|
||||
"", "Esc", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "-", "=", "Backspace", "Tab",
|
||||
"Q", "W", "E", "R", "T", "Y", "U", "I",
|
||||
"O", "P", "[", "]", "Enter", "Lewy Ctrl", "A", "S",
|
||||
|
||||
"D", "F", "G", "H", "J", "K", "L", ";",
|
||||
"'", "`", "LShift", "\\", "Z", "X", "C", "V",
|
||||
"B", "N", "M", ",", ".", "/", "PShift", "Num *",
|
||||
"Alt", "Spacja", "CapsLock", "F1", "F2", "F3", "F4", "F5",
|
||||
|
||||
"F6", "F7", "F8", "F9", "F10", "Pause", "Scrlock", "Num 7",
|
||||
"Num 8", "Num 9", "Num -", "Num 4", "Num 5", "Num 6", "Num +", "Num 1",
|
||||
"Num 2", "Num 3", "Num 0", "Num .", "", "", "", "F11",
|
||||
"F12", "", "", "", "", "", "", "",
|
||||
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "Num Enter", "Prawy Ctrl", "", "",
|
||||
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "Num /", "", "PrntScr",
|
||||
"Alt", "", "", "", "", "", "", "",
|
||||
|
||||
"", "", "", "", "", "Num Lock", "", "Home",
|
||||
"Kursor G\xF3ra", "Page Up", "", "Kursor Lewo", "", "Kursor Prawo", "", "End",
|
||||
"Kursor D\xF3\xB3", "Page Down", "Insert", "Delete", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "",
|
||||
};
|
||||
|
||||
char *Joy_button_text_polish[] = {
|
||||
"Przyc.1", "Przyc.2", "Przyc.3", "Przyc.4", "Przyc.5", "Przyc.6",
|
||||
"Przyc.7", "Przyc.8", "Przyc.9", "Przyc.10", "Przyc.11", "Przyc.12",
|
||||
"Przyc.13", "Przyc.14", "Przyc.15", "Przyc.16", "Przyc.17", "Przyc.18",
|
||||
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
|
||||
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
|
||||
"Przyc.31", "Przyc.32", "Hat Ty\xB3", "Hat Prz\xF3\x64", "Hat Lewo", "Hat Prawo"
|
||||
};
|
||||
|
||||
//! This is the text that is displayed on the screen for the keys a player selects
|
||||
// This is the text that is displayed on the screen for the keys a player selects
|
||||
char *Scan_code_text_english[] = {
|
||||
"", "Esc", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "0", "-", "=", "Backspace", "Tab",
|
||||
@@ -403,9 +343,6 @@ char *Joy_button_text_english[] = {
|
||||
char **Scan_code_text = Scan_code_text_english;
|
||||
char **Joy_button_text = Joy_button_text_english;
|
||||
|
||||
SCP_vector<config_item*> Control_config_presets;
|
||||
SCP_vector<SCP_string> Control_config_preset_names;
|
||||
|
||||
void set_modifier_status()
|
||||
{
|
||||
int i;
|
||||
@@ -431,14 +368,17 @@ void set_modifier_status()
|
||||
}
|
||||
}
|
||||
|
||||
// If find_override is set to true, then this returns the index of the action
|
||||
// which has been bound to the given key. Otherwise, the index of the action
|
||||
// which has the given key as its default key will be returned.
|
||||
int translate_key_to_index(const char *key, bool find_override)
|
||||
int translate_key_to_index(char *key)
|
||||
{
|
||||
int i, index = -1, alt = 0, shift = 0, max_scan_codes;
|
||||
|
||||
max_scan_codes = sizeof(Scan_code_text_english) / sizeof(char *);
|
||||
if (Lcl_gr) {
|
||||
max_scan_codes = sizeof(Scan_code_text_german) / sizeof(char *);
|
||||
} else if (Lcl_fr) {
|
||||
max_scan_codes = sizeof(Scan_code_text_french) / sizeof(char *);
|
||||
} else {
|
||||
max_scan_codes = sizeof(Scan_code_text_english) / sizeof(char *);
|
||||
}
|
||||
|
||||
// look for modifiers
|
||||
Assert(key);
|
||||
@@ -449,7 +389,17 @@ int translate_key_to_index(const char *key, bool find_override)
|
||||
key++;
|
||||
}
|
||||
|
||||
if (!strnicmp(key, "Shift", 5)) {
|
||||
char *translated_shift;
|
||||
|
||||
if(Lcl_gr){
|
||||
translated_shift = "Shift";
|
||||
} else if(Lcl_fr){
|
||||
translated_shift = "Maj.";
|
||||
} else {
|
||||
translated_shift = "Shift";
|
||||
}
|
||||
|
||||
if (!strnicmp(key, translated_shift, 5)) {
|
||||
shift = 1;
|
||||
key += 5;
|
||||
if (*key)
|
||||
@@ -473,19 +423,10 @@ int translate_key_to_index(const char *key, bool find_override)
|
||||
index |= KEY_ALTED;
|
||||
|
||||
// convert scancode to Control_config index
|
||||
if (find_override) {
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (!Control_config[i].disabled && Control_config[i].key_id == index) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (!Control_config[i].disabled && Control_config[i].key_default == index) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (Control_config[i].key_default == index) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,55 +439,27 @@ int translate_key_to_index(const char *key, bool find_override)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*! Given the system default key 'key', return the current key that is bound to that function.
|
||||
* Both are 'key' and the return value are descriptive strings that can be displayed
|
||||
* directly to the user. If 'key' isn't a real key, is not normally bound to anything,
|
||||
* or there is no key currently bound to the function, NULL is returned.
|
||||
*/
|
||||
// Given the system default key 'key', return the current key that is bound to the function
|
||||
// Both are 'key' and the return value are descriptive strings that can be displayed
|
||||
// directly to the user. If 'key' isn't a real key or not normally bound to anything,
|
||||
// or there is no key current bound to the function, NULL is returned.
|
||||
char *translate_key(char *key)
|
||||
{
|
||||
int index = -1, key_code = -1, joy_code = -1;
|
||||
char *key_text = NULL;
|
||||
char *joy_text = NULL;
|
||||
int index = -1, code = -1;
|
||||
|
||||
static char text[40] = {"None"};
|
||||
|
||||
index = translate_key_to_index(key, false);
|
||||
if (index < 0) {
|
||||
index = translate_key_to_index(key);
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key_code = Control_config[index].key_id;
|
||||
joy_code = Control_config[index].joy_id;
|
||||
|
||||
code = Control_config[index].key_id;
|
||||
Failed_key_index = index;
|
||||
|
||||
if (key_code >= 0) {
|
||||
key_text = textify_scancode(key_code);
|
||||
if (code < 0) {
|
||||
code = Control_config[index].joy_id;
|
||||
if (code >= 0)
|
||||
return Joy_button_text[code];
|
||||
}
|
||||
|
||||
if (joy_code >= 0) {
|
||||
joy_text = Joy_button_text[joy_code];
|
||||
}
|
||||
|
||||
// both key and joystick button are mapped to this control
|
||||
if ((key_code >= 0 ) && (joy_code >= 0) ) {
|
||||
strcpy_s(text, key_text);
|
||||
strcat_s(text, " or ");
|
||||
strcat_s(text, joy_text);
|
||||
}
|
||||
// if we only have one
|
||||
else if (key_code >= 0 ) {
|
||||
strcpy_s(text, key_text);
|
||||
}
|
||||
else if (joy_code >= 0) {
|
||||
strcpy_s(text, joy_text);
|
||||
}
|
||||
else {
|
||||
strcpy_s(text, "None");
|
||||
}
|
||||
|
||||
return text;
|
||||
return textify_scancode(code);
|
||||
}
|
||||
|
||||
char *textify_scancode(int code)
|
||||
@@ -584,341 +497,23 @@ char *textify_scancode(int code)
|
||||
}
|
||||
//XSTR:ON
|
||||
|
||||
void control_config_common_load_overrides();
|
||||
|
||||
// initialize common control config stuff - call at game startup after localization has been initialized
|
||||
void control_config_common_init()
|
||||
{
|
||||
for (int i=0; i<CCFG_MAX; i++) {
|
||||
Control_config[i].disabled = false;
|
||||
Control_config[i].continuous_ongoing = false;
|
||||
}
|
||||
|
||||
control_config_common_load_overrides();
|
||||
if(Lcl_gr){
|
||||
Scan_code_text = Scan_code_text_german;
|
||||
Joy_button_text = Joy_button_text_german;
|
||||
|
||||
// swap init bindings for y and z keys
|
||||
Control_config[TARGET_SHIP_IN_RETICLE].key_default = KEY_Z;
|
||||
Control_config[TARGET_LAST_TRANMISSION_SENDER].key_default = KEY_ALTED | KEY_Z;
|
||||
Control_config[REVERSE_THRUST].key_default = KEY_Y;
|
||||
Control_config[DISARM_MESSAGE].key_default = KEY_SHIFTED | KEY_Y;
|
||||
} else if(Lcl_fr){
|
||||
Scan_code_text = Scan_code_text_french;
|
||||
Joy_button_text = Joy_button_text_french;
|
||||
} else if(Lcl_pl){
|
||||
Scan_code_text = Scan_code_text_polish;
|
||||
Joy_button_text = Joy_button_text_polish;
|
||||
} else {
|
||||
Scan_code_text = Scan_code_text_english;
|
||||
Joy_button_text = Joy_button_text_english;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief close any common control config stuff, called at game_shutdown()
|
||||
*/
|
||||
void control_config_common_close()
|
||||
{
|
||||
// only need to worry control presets for now
|
||||
for (auto ii = Control_config_presets.cbegin(); ii != Control_config_presets.cend(); ++ii) {
|
||||
delete[] * ii;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
SCP_map<SCP_string, int> mKeyNameToVal;
|
||||
SCP_map<SCP_string, CC_type> mCCTypeNameToVal;
|
||||
SCP_map<SCP_string, char> mCCTabNameToVal;
|
||||
|
||||
/*! Helper function to LoadEnumsIntoMaps(), Loads the Keyboard definitions/enumerations into mKeyNameToVal
|
||||
*/
|
||||
void LoadEnumsIntoKeyMap(void) {
|
||||
// Dirty macro hack :D
|
||||
#define ADD_ENUM_TO_KEY_MAP(Enum) mKeyNameToVal[#Enum] = (Enum);
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SHIFTED)
|
||||
/*
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_ALTED)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_CTRLED)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DEBUGGED)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DEBUGGED1)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_MASK)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DEBUG_KEY)
|
||||
*/
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_0)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_1)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_2)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_3)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_4)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_5)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_6)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_7)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_8)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_9)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_A)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_B)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_C)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_D)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_E)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_G)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_H)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_I)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_J)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_K)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_L)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_M)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_N)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_O)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_P)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_Q)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_R)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_S)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_T)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_U)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_V)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_W)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_X)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_Y)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_Z)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_MINUS)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_EQUAL)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DIVIDE)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SLASH)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SLASH_UK)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_COMMA)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PERIOD)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SEMICOL)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LBRACKET)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RBRACKET)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RAPOSTRO)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LAPOSTRO)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_ESC)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_ENTER)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_BACKSP)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_TAB)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SPACEBAR)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_NUMLOCK)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_SCROLLOCK)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_CAPSLOCK)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LSHIFT)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RSHIFT)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LALT)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RALT)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LCTRL)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RCTRL)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F1)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F2)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F3)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F4)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F5)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F6)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F7)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F8)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F9)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F10)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F11)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_F12)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD0)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD1)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD2)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD3)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD4)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD5)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD6)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD7)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD8)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAD9)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADMINUS)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADPLUS)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADPERIOD)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADDIVIDE)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADMULTIPLY)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PADENTER)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_INSERT)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_HOME)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAGEUP)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DELETE)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_END)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAGEDOWN)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_UP)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_DOWN)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_LEFT)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_RIGHT)
|
||||
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PRINT_SCRN)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_PAUSE)
|
||||
ADD_ENUM_TO_KEY_MAP(KEY_BREAK)
|
||||
|
||||
#undef ADD_ENUM_TO_KEY_MAP
|
||||
}
|
||||
|
||||
/*! Helper function to LoadEnumsIntoMaps(), Loads the Control Types enumerations into mCCTypeNameToVal
|
||||
*/
|
||||
void LoadEnumsIntoCCTypeMap(void) {
|
||||
// Dirty macro hack :D
|
||||
#define ADD_ENUM_TO_CCTYPE_MAP(Enum) mCCTypeNameToVal[#Enum] = (Enum);
|
||||
|
||||
ADD_ENUM_TO_CCTYPE_MAP(CC_TYPE_TRIGGER)
|
||||
ADD_ENUM_TO_CCTYPE_MAP(CC_TYPE_CONTINUOUS)
|
||||
|
||||
#undef ADD_ENUM_TO_CCTYPE_MAP
|
||||
}
|
||||
|
||||
/*! Helper function to LoadEnumsIntoMaps(), Loads the Control Tabs enumerations into mCCTabNameToVal
|
||||
*/
|
||||
void LoadEnumsIntoCCTabMap(void) {
|
||||
// Dirty macro hack :D
|
||||
#define ADD_ENUM_TO_CCTAB_MAP(Enum) mCCTabNameToVal[#Enum] = (Enum);
|
||||
|
||||
ADD_ENUM_TO_CCTAB_MAP(TARGET_TAB)
|
||||
ADD_ENUM_TO_CCTAB_MAP(SHIP_TAB)
|
||||
ADD_ENUM_TO_CCTAB_MAP(WEAPON_TAB)
|
||||
ADD_ENUM_TO_CCTAB_MAP(COMPUTER_TAB)
|
||||
|
||||
#undef ADD_ENUM_TO_CCTAB_MAP
|
||||
}
|
||||
|
||||
/*! Loads the various control configuration maps to allow the parsing functions to appropriately map string tokns to
|
||||
* their associated enumerations. The string tokens in the controlconfigdefaults.tbl match directly to their names in
|
||||
* the C++ code, such as "KEY_5" in the .tbl mapping to the #define KEY_5 value
|
||||
*/
|
||||
void LoadEnumsIntoMaps() {
|
||||
LoadEnumsIntoKeyMap();
|
||||
LoadEnumsIntoCCTypeMap();
|
||||
LoadEnumsIntoCCTabMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parses controlconfigdefault.tbl, and overrides the default control configuration for each valid entry in the .tbl
|
||||
*/
|
||||
void control_config_common_load_overrides()
|
||||
{
|
||||
LoadEnumsIntoMaps();
|
||||
|
||||
if (cf_exists_full("controlconfigdefaults.tbl", CF_TYPE_TABLES)) {
|
||||
read_file_text("controlconfigdefaults.tbl", CF_TYPE_TABLES);
|
||||
} else {
|
||||
read_file_text_from_array(defaults_get_file("controlconfigdefaults.tbl"));
|
||||
}
|
||||
|
||||
reset_parse();
|
||||
|
||||
// start parsing
|
||||
// TODO: Split this out into more helps. Too many tabs!
|
||||
while(optional_string("#ControlConfigOverride")) {
|
||||
config_item *cfg_preset = new config_item[CCFG_MAX + 1];
|
||||
std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset);
|
||||
Control_config_presets.push_back(cfg_preset);
|
||||
|
||||
SCP_string preset_name;
|
||||
if (optional_string("$Name:")) {
|
||||
stuff_string_line(preset_name);
|
||||
} else {
|
||||
preset_name = "<unnamed preset>";
|
||||
}
|
||||
Control_config_preset_names.push_back(preset_name);
|
||||
|
||||
while (required_string_either("#End","$Bind Name:")) {
|
||||
const int iBufferLength = 64;
|
||||
char szTempBuffer[iBufferLength];
|
||||
|
||||
required_string("$Bind Name:");
|
||||
stuff_string(szTempBuffer, F_NAME, iBufferLength);
|
||||
|
||||
const size_t cCntrlAryLength = sizeof(Control_config) / sizeof(Control_config[0]);
|
||||
for (size_t i = 0; i < cCntrlAryLength; ++i) {
|
||||
config_item& r_ccConfig = cfg_preset[i];
|
||||
|
||||
if (!strcmp(szTempBuffer, r_ccConfig.text)) {
|
||||
/**
|
||||
* short key_default;
|
||||
* short joy_default;
|
||||
* char tab;
|
||||
* bool hasXSTR;
|
||||
* char type;
|
||||
*/
|
||||
|
||||
int iTemp;
|
||||
|
||||
if (optional_string("$Key Default:")) {
|
||||
if (optional_string("NONE")) {
|
||||
r_ccConfig.key_default = (short)-1;
|
||||
} else {
|
||||
stuff_string(szTempBuffer, F_NAME, iBufferLength);
|
||||
r_ccConfig.key_default = (short)mKeyNameToVal[szTempBuffer];
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Joy Default:")) {
|
||||
stuff_int(&iTemp);
|
||||
r_ccConfig.joy_default = (short)iTemp;
|
||||
}
|
||||
|
||||
if (optional_string("$Key Mod Shift:")) {
|
||||
stuff_int(&iTemp);
|
||||
r_ccConfig.key_default |= (iTemp == 1) ? KEY_SHIFTED : 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Key Mod Alt:")) {
|
||||
stuff_int(&iTemp);
|
||||
r_ccConfig.key_default |= (iTemp == 1) ? KEY_ALTED : 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Key Mod Ctrl:")) {
|
||||
stuff_int(&iTemp);
|
||||
r_ccConfig.key_default |= (iTemp == 1) ? KEY_CTRLED : 0;
|
||||
}
|
||||
|
||||
if (optional_string("$Category:")) {
|
||||
stuff_string(szTempBuffer, F_NAME, iBufferLength);
|
||||
r_ccConfig.tab = (char)mCCTabNameToVal[szTempBuffer];
|
||||
}
|
||||
|
||||
if (optional_string("$Has XStr:")) {
|
||||
stuff_int(&iTemp);
|
||||
r_ccConfig.hasXSTR = (iTemp == 1);
|
||||
}
|
||||
|
||||
if (optional_string("$Type:")) {
|
||||
stuff_string(szTempBuffer, F_NAME, iBufferLength);
|
||||
r_ccConfig.type = (char)mCCTypeNameToVal[szTempBuffer];
|
||||
}
|
||||
|
||||
if (optional_string("+Disable")) {
|
||||
r_ccConfig.disabled = true;
|
||||
}
|
||||
if (optional_string("$Disable:")) {
|
||||
stuff_boolean(&r_ccConfig.disabled);
|
||||
}
|
||||
|
||||
// Nerf the buffer now.
|
||||
szTempBuffer[0] = '\0';
|
||||
} else if ((i + 1) == cCntrlAryLength) {
|
||||
error_display(1, "Bind Name not found: %s\n", szTempBuffer);
|
||||
advance_to_eoln(NULL);
|
||||
ignore_white_space();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
// Overwrite the control config with the first preset that was found
|
||||
if (Control_config_presets.size() > 0) {
|
||||
std::copy(Control_config_presets[0], Control_config_presets[0] + CCFG_MAX + 1, Control_config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "globalincs/crypt.h"
|
||||
|
||||
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redfine main() which is something
|
||||
// that we don't want since we don't actually link against SDL, this solves the problem...
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *crypt_string;
|
||||
|
||||
if ( argc == 1 ) {
|
||||
printf("Usage: cryptstring <string1> <string2> ...\n");
|
||||
printf("Output will be <crypt1> <crypt2>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for ( i = 1; i < argc; i++ ) {
|
||||
char *s;
|
||||
|
||||
s = argv[i];
|
||||
// if the length of the string is greater than the number of crypted symbols we
|
||||
// return, then pass only the maximum length
|
||||
if ( strlen(s) > CRYPT_STRING_LENGTH )
|
||||
s += (strlen(s) - CRYPT_STRING_LENGTH);
|
||||
|
||||
crypt_string = jcrypt(s);
|
||||
printf("%s\n", crypt_string);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *jcrypt (char *plainstring)
|
||||
{
|
||||
int i,t,len;
|
||||
static char cryptstring[CRYPT_STRING_LENGTH + 1];
|
||||
|
||||
len=strlen (plainstring);
|
||||
if (len > CRYPT_STRING_LENGTH)
|
||||
len = CRYPT_STRING_LENGTH;
|
||||
|
||||
for (i = 0;i < len; i++) {
|
||||
cryptstring[i]=0;
|
||||
|
||||
for (t = 0; t < len; t++) {
|
||||
cryptstring[i]^=(plainstring[t] ^ plainstring[i%(t+1)]);
|
||||
cryptstring[i]%=90;
|
||||
cryptstring[i]+=33;
|
||||
}
|
||||
}
|
||||
|
||||
cryptstring[i]=0;
|
||||
return ((char *)cryptstring);
|
||||
}
|
||||
+124
-98
@@ -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,20 @@ 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) {
|
||||
vm_free(cut->description);
|
||||
cut->description = NULL;
|
||||
}
|
||||
for(size_t i = 0; i < Cutscenes.size(); i++)
|
||||
{
|
||||
if(Cutscenes[i].description)
|
||||
{
|
||||
vm_free(Cutscenes[i].description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialization stuff for cutscenes
|
||||
@@ -52,74 +56,72 @@ 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
|
||||
// returns -1 on failure.
|
||||
int cutscenes_get_cd_num( char *filename )
|
||||
{
|
||||
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) {
|
||||
if ( !stricmp(cut->filename, filename) ) {
|
||||
return (cut->cd - 1);
|
||||
#if defined(OEM_BUILD)
|
||||
return 0; // only 1 cd for OEM
|
||||
#else
|
||||
|
||||
for (size_t i = 0; i < Cutscenes.size(); i++ ) {
|
||||
if ( !stricmp(Cutscenes[i].filename, filename) ) {
|
||||
return (Cutscenes[i].cd - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
#endif // defined(OEM_BUILD)
|
||||
}
|
||||
|
||||
// marks a cutscene as viewable
|
||||
@@ -139,21 +141,18 @@ void cutscene_mark_viewable(char *filename)
|
||||
|
||||
// change to lower case
|
||||
strlwr(file);
|
||||
int i = 0;
|
||||
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) {
|
||||
|
||||
for (size_t i = 0; i < Cutscenes.size(); i++ ) {
|
||||
// change the cutscene file name to lower case
|
||||
strcpy_s(cut_file, cut->filename);
|
||||
strcpy_s(cut_file, Cutscenes[i].filename);
|
||||
strlwr(cut_file);
|
||||
|
||||
// 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
|
||||
@@ -168,6 +167,7 @@ void cutscene_mark_viewable(char *filename)
|
||||
#define PLAY_BUTTON 6
|
||||
#define EXIT_BUTTON 7
|
||||
|
||||
static int Num_files;
|
||||
static SCP_vector<int> Cutscene_list;
|
||||
//static int Stats_scroll_offset; // not used - taylor
|
||||
static int Selected_line = 0; // line that is currently selected for binding
|
||||
@@ -252,7 +252,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,9 +260,11 @@ 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];
|
||||
|
||||
#ifdef RELEASE_REAL
|
||||
int num_attempts = 0;
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
int path_set_ok;
|
||||
@@ -273,7 +275,12 @@ int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(OEM_BUILD)
|
||||
sprintf(volume_name, NOX("FS2_OEM"));
|
||||
#else
|
||||
sprintf(volume_name, NOX("FREESPACE2_%c"), '1' + cd_mve_is_on);
|
||||
#endif
|
||||
|
||||
|
||||
cd_drive_num = find_freespace_cd(volume_name);
|
||||
path_set_ok = set_cdrom_path(cd_drive_num);
|
||||
@@ -283,6 +290,7 @@ int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef RELEASE_REAL
|
||||
if ( !prompt_for_cd ) {
|
||||
cd_present = 0;
|
||||
break;
|
||||
@@ -292,7 +300,11 @@ int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
char popup_msg[256];
|
||||
int popup_rval;
|
||||
|
||||
#if defined(DVD_MESSAGE_HACK)
|
||||
sprintf(popup_msg, XSTR( "Movie not found\n\nInsert FreeSpace DVD to continue", 203));
|
||||
#else
|
||||
sprintf(popup_msg, XSTR( "Movie not found\n\nInsert FreeSpace CD #%d to continue", 203), cd_mve_is_on+1);
|
||||
#endif
|
||||
|
||||
popup_rval = popup(PF_BODY_BIG, 2, POPUP_CANCEL, POPUP_OK, popup_msg);
|
||||
if ( popup_rval != 1 ) {
|
||||
@@ -304,6 +316,11 @@ int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
|
||||
cd_present = 0;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
cd_present = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return cd_present;
|
||||
@@ -314,13 +331,13 @@ void cutscenes_screen_play()
|
||||
char name[MAX_FILENAME_LEN]; // *full_name
|
||||
int which_cutscene;
|
||||
|
||||
Assert( (Selected_line >= 0) && (Selected_line < (int)Cutscene_list.size()) );
|
||||
Assert( (Selected_line >= 0) && (Selected_line < Num_files) );
|
||||
which_cutscene = Cutscene_list[Selected_line];
|
||||
|
||||
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 +346,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 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -355,7 +372,7 @@ void cutscenes_screen_scroll_line_down()
|
||||
{
|
||||
int h;
|
||||
|
||||
if (Selected_line < (int)Cutscene_list.size() - 1) {
|
||||
if (Selected_line < Num_files - 1) {
|
||||
Selected_line++;
|
||||
gamesnd_play_iface(SND_SCROLL);
|
||||
|
||||
@@ -392,7 +409,7 @@ void cutscenes_screen_scroll_screen_down()
|
||||
int h;
|
||||
|
||||
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
|
||||
if (Scroll_offset + h < (int)Cutscene_list.size()) {
|
||||
if (Scroll_offset + h < Num_files) {
|
||||
Scroll_offset++;
|
||||
if (Selected_line < Scroll_offset){
|
||||
Selected_line = Scroll_offset;
|
||||
@@ -482,12 +499,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.
|
||||
|
||||
Num_files = 0;
|
||||
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);
|
||||
for (size_t j = 0; j < Cutscenes.size(); j++ ) {
|
||||
if ( Cutscenes_viewable & (1<<j) ) {
|
||||
Cutscene_list.push_back((int)j);
|
||||
Num_files++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -545,10 +570,11 @@ void cutscenes_screen_do_frame()
|
||||
// the "show-all" hotkey
|
||||
case KEY_CTRLED | KEY_SHIFTED | KEY_S:
|
||||
{
|
||||
Num_files = 0;
|
||||
Cutscene_list.clear();
|
||||
size_t size = Cutscenes.size();
|
||||
for (size_t t = 0; t < size; t++) {
|
||||
for (size_t t = 0; t < Cutscenes.size(); t++) {
|
||||
Cutscene_list.push_back((int)t);
|
||||
Num_files++;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -566,21 +592,21 @@ void cutscenes_screen_do_frame()
|
||||
if (List_region.button_down()) {
|
||||
List_region.get_mouse_pos(NULL, &y);
|
||||
z = Scroll_offset + y / font_height;
|
||||
if ((z >= 0) && (z < (int)Cutscene_list.size()))
|
||||
if ((z >= 0) && (z < Num_files))
|
||||
select_tease_line = z;
|
||||
}
|
||||
|
||||
if (List_region.pressed()) {
|
||||
List_region.get_mouse_pos(NULL, &y);
|
||||
z = Scroll_offset + y / font_height;
|
||||
if ((z >= 0) && (z < (int)Cutscene_list.size()))
|
||||
if ((z >= 0) && (z < Num_files))
|
||||
Selected_line = z;
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -598,7 +624,7 @@ void cutscenes_screen_do_frame()
|
||||
y = 0;
|
||||
z = Scroll_offset;
|
||||
while (y + font_height <= Cutscene_list_coords[gr_screen.res][3]) {
|
||||
if (z >= (int)Cutscene_list.size()){
|
||||
if (z >= Num_files){
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -610,7 +636,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++;
|
||||
@@ -640,7 +666,7 @@ void cutscenes_screen_do_frame()
|
||||
y = 0;
|
||||
z = Text_offset;
|
||||
while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3]) {
|
||||
if (z >= Text_size || z >= MAX_TEXT_LINES-1)
|
||||
if (z >= Text_size)
|
||||
break;
|
||||
|
||||
len = Text_line_size[z];
|
||||
@@ -649,7 +675,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();
|
||||
|
||||
+114
-30
@@ -10,14 +10,18 @@ extern void *g_vBackBuf1, *g_vBackBuf2;
|
||||
static ushort *backBuf1, *backBuf2;
|
||||
static int lookup_initialized;
|
||||
|
||||
static void dispatchDecoder16(ushort **pFrame, ubyte codeType, ubyte **pData, ubyte **pOffData, int *pDataRemain, int *curXb, int *curYb);
|
||||
static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
|
||||
static void genLoopkupTable();
|
||||
|
||||
void decodeFrame16(ubyte *pFrame, ubyte *pMap, int mapRemain, unsigned char *pData, int dataRemain)
|
||||
void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain)
|
||||
{
|
||||
ubyte *pOrig, *pOffData, op;
|
||||
unsigned char *pOrig;
|
||||
unsigned char *pOffData, *pEnd;
|
||||
ushort offset;
|
||||
int length = 0, i, j, xb, yb;
|
||||
int length;
|
||||
int op;
|
||||
int i, j;
|
||||
int xb, yb;
|
||||
|
||||
if (!lookup_initialized) {
|
||||
genLoopkupTable();
|
||||
@@ -32,6 +36,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 +59,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))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +156,21 @@ static void patternRow4Pixels2(ushort *pFrame, unsigned char pat0, ushort *p)
|
||||
unsigned char mask=0x03;
|
||||
unsigned char shift=0;
|
||||
ushort pel;
|
||||
/* ORIGINAL VERSION IS BUGGY
|
||||
int skip=1;
|
||||
|
||||
while (mask != 0) {
|
||||
pel = p[(mask & pat0) >> shift];
|
||||
pFrame[0] = pel;
|
||||
pFrame[2] = pel;
|
||||
pFrame[g_width + 0] = pel;
|
||||
pFrame[g_width + 2] = pel;
|
||||
pFrame += skip;
|
||||
skip = 4 - skip;
|
||||
mask <<= 2;
|
||||
shift += 2;
|
||||
}
|
||||
*/
|
||||
while (mask != 0) {
|
||||
pel = p[(mask & pat0) >> shift];
|
||||
pFrame[0] = pel;
|
||||
@@ -190,9 +208,10 @@ static void patternQuadrant4Pixels(ushort *pFrame, unsigned char pat0, unsigned
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
pFrame[i&3] = p[(pat & mask) >> shift];
|
||||
if ((i&3) == 3) {
|
||||
|
||||
if ((i&3) == 3)
|
||||
pFrame += g_width;
|
||||
}
|
||||
|
||||
mask <<= 2;
|
||||
shift += 2;
|
||||
}
|
||||
@@ -213,6 +232,19 @@ static void patternRow2Pixels2(ushort *pFrame, unsigned char pat, ushort *p)
|
||||
ushort pel;
|
||||
unsigned char mask=0x1;
|
||||
|
||||
/* ORIGINAL VERSION IS BUGGY
|
||||
int skip=1;
|
||||
while (mask != 0x10) {
|
||||
pel = p[(mask & pat) ? 1 : 0];
|
||||
pFrame[0] = pel;
|
||||
pFrame[2] = pel;
|
||||
pFrame[g_width + 0] = pel;
|
||||
pFrame[g_width + 2] = pel;
|
||||
pFrame += skip;
|
||||
skip = 4 - skip;
|
||||
mask <<= 1;
|
||||
}
|
||||
*/
|
||||
while (mask != 0x10) {
|
||||
pel = p[(mask & pat) ? 1 : 0];
|
||||
|
||||
@@ -234,9 +266,10 @@ static void patternQuadrant2Pixels(ushort *pFrame, unsigned char pat0, unsigned
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
pFrame[i&3] = p[(pat & mask) ? 1 : 0];
|
||||
if ((i&3) == 3) {
|
||||
|
||||
if ((i&3) == 3)
|
||||
pFrame += g_width;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
@@ -255,63 +288,76 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
switch(codeType) {
|
||||
case 0x0:
|
||||
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1));
|
||||
break; // ADDED
|
||||
break; // ADDED
|
||||
|
||||
case 0x1:
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
/* relFar(*(*pOffData)++, 1, &x, &y); */
|
||||
|
||||
k = *(*pOffData)++;
|
||||
x = far_p_table[k*2+0];
|
||||
y = far_p_table[k*2+1];
|
||||
|
||||
copyFrame(*pFrame, *pFrame + x + y*g_width);
|
||||
(*pDataRemain)--;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x3:
|
||||
/* relFar(*(*pOffData)++, -1, &x, &y); */
|
||||
|
||||
k = *(*pOffData)++;
|
||||
x = far_n_table[k*2+0];
|
||||
y = far_n_table[k*2+1];
|
||||
|
||||
copyFrame(*pFrame, *pFrame + x + y*g_width);
|
||||
(*pDataRemain)--;
|
||||
break;
|
||||
(*pDataRemain)--;
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
/* relClose(*(*pOffData)++, &x, &y); */
|
||||
|
||||
k = *(*pOffData)++;
|
||||
x = close_table[k*2+0];
|
||||
y = close_table[k*2+1];
|
||||
|
||||
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
|
||||
(*pDataRemain)--;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
x = (char)*(*pData)++;
|
||||
y = (char)*(*pData)++;
|
||||
copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width);
|
||||
*pDataRemain -= 2;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x6:
|
||||
nprintf(("MVE", "STUB: encoding 6 not tested\n"));
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
*pFrame += 16;
|
||||
|
||||
if (++*curXb == (g_width >> 3)) {
|
||||
*pFrame += 7*g_width;
|
||||
*curXb = 0;
|
||||
if (++*curYb == (g_height >> 3)) {
|
||||
|
||||
if (++*curYb == (g_height >> 3))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
p[0] = GETPIXELI(pData, 0);
|
||||
p[1] = GETPIXELI(pData, 0);
|
||||
|
||||
if (!((p[0]/*|p[1]*/)&0x8000)) {
|
||||
for (i=0; i<8; i++) {
|
||||
patternRow2Pixels(*pFrame, *(*pData), p);
|
||||
(*pData)++;
|
||||
|
||||
*pFrame += g_width;
|
||||
}
|
||||
} else {
|
||||
@@ -320,21 +366,26 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
*pFrame += 2*g_width;
|
||||
patternRow2Pixels2(*pFrame, *(*pData) >> 4, p);
|
||||
(*pData)++;
|
||||
|
||||
*pFrame += 2*g_width;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
p[0] = GETPIXEL(pData, 0);
|
||||
|
||||
if (!(p[0] & 0x8000)) {
|
||||
for (i=0; i<4; i++) {
|
||||
p[0] = GETPIXELI(pData, 0);
|
||||
p[1] = GETPIXELI(pData, 0);
|
||||
|
||||
pat[0] = (*pData)[0];
|
||||
pat[1] = (*pData)[1];
|
||||
(*pData) += 2;
|
||||
|
||||
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
|
||||
|
||||
if (i & 1) {
|
||||
*pFrame -= (4*g_width - 4);
|
||||
} else {
|
||||
@@ -343,6 +394,7 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
}
|
||||
} else {
|
||||
p[2] = GETPIXEL(pData, 8);
|
||||
|
||||
if (!(p[2]&0x8000)) {
|
||||
for (i=0; i<4; i++) {
|
||||
if ((i & 1) == 0) {
|
||||
@@ -352,6 +404,7 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
pat[0] = *(*pData)++;
|
||||
pat[1] = *(*pData)++;
|
||||
patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p);
|
||||
|
||||
if (i & 1) {
|
||||
*pFrame -= (4*g_width - 4);
|
||||
} else {
|
||||
@@ -366,18 +419,21 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
}
|
||||
patternRow2Pixels(*pFrame, *(*pData), p);
|
||||
(*pData)++;
|
||||
|
||||
*pFrame += g_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0x9:
|
||||
p[0] = GETPIXELI(pData, 0);
|
||||
p[1] = GETPIXELI(pData, 0);
|
||||
p[2] = GETPIXELI(pData, 0);
|
||||
p[3] = GETPIXELI(pData, 0);
|
||||
|
||||
*pDataRemain -= 8;
|
||||
|
||||
if (!(p[0] & 0x8000)) {
|
||||
if (!(p[2] & 0x8000)) {
|
||||
for (i=0; i<8; i++) {
|
||||
@@ -396,6 +452,7 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
patternRow4Pixels2(*pFrame, (*pData)[2], p);
|
||||
*pFrame += 2*g_width;
|
||||
patternRow4Pixels2(*pFrame, (*pData)[3], p);
|
||||
|
||||
(*pData) += 4;
|
||||
*pDataRemain -= 4;
|
||||
}
|
||||
@@ -412,7 +469,9 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
for (i=0; i<4; i++) {
|
||||
pat[0] = (*pData)[0];
|
||||
pat[1] = (*pData)[1];
|
||||
|
||||
(*pData) += 2;
|
||||
|
||||
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
|
||||
*pFrame += g_width;
|
||||
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
|
||||
@@ -421,10 +480,11 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
*pDataRemain -= 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xa:
|
||||
p[0] = GETPIXEL(pData, 0);
|
||||
|
||||
if (!(p[0] & 0x8000)) {
|
||||
for (i=0; i<4; i++) {
|
||||
p[0] = GETPIXELI(pData, 0);
|
||||
@@ -435,8 +495,11 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
pat[1] = (*pData)[1];
|
||||
pat[2] = (*pData)[2];
|
||||
pat[3] = (*pData)[3];
|
||||
|
||||
(*pData) += 4;
|
||||
|
||||
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
|
||||
|
||||
if (i & 1) {
|
||||
*pFrame -= (4*g_width - 4);
|
||||
} else {
|
||||
@@ -445,6 +508,7 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
}
|
||||
} else {
|
||||
p[0] = GETPIXEL(pData, 16);
|
||||
|
||||
if (!(p[0] & 0x8000)) {
|
||||
for (i=0; i<4; i++) {
|
||||
if ((i&1) == 0) {
|
||||
@@ -453,12 +517,16 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
p[2] = GETPIXELI(pData, 0);
|
||||
p[3] = GETPIXELI(pData, 0);
|
||||
}
|
||||
|
||||
pat[0] = (*pData)[0];
|
||||
pat[1] = (*pData)[1];
|
||||
pat[2] = (*pData)[2];
|
||||
pat[3] = (*pData)[3];
|
||||
|
||||
(*pData) += 4;
|
||||
|
||||
patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p);
|
||||
|
||||
if (i & 1) {
|
||||
*pFrame -= (4*g_width - 4);
|
||||
} else {
|
||||
@@ -473,21 +541,24 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
p[2] = GETPIXELI(pData, 0);
|
||||
p[3] = GETPIXELI(pData, 0);
|
||||
}
|
||||
|
||||
pat[0] = (*pData)[0];
|
||||
pat[1] = (*pData)[1];
|
||||
patternRow4Pixels(*pFrame, pat[0], pat[1], p);
|
||||
*pFrame += g_width;
|
||||
|
||||
(*pData) += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
for (i=0; i<8; i++) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
ubyte frame_tmp[16];
|
||||
memcpy(&frame_tmp, *pData, 16);
|
||||
|
||||
ushort *swap_tmp;
|
||||
for (j = 0; j < 16; j += 2) {
|
||||
swap_tmp = (ushort*)(frame_tmp + j);
|
||||
@@ -501,7 +572,7 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
*pData += 16;
|
||||
*pDataRemain -= 16;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
for (i=0; i<4; i++) {
|
||||
@@ -509,61 +580,74 @@ static void dispatchDecoder16(ushort **pFrame, unsigned char codeType, unsigned
|
||||
p[1] = GETPIXEL(pData, 2);
|
||||
p[2] = GETPIXEL(pData, 4);
|
||||
p[3] = GETPIXEL(pData, 6);
|
||||
|
||||
for (j=0; j<2; j++) {
|
||||
for (k=0; k<4; k++) {
|
||||
(*pFrame)[2*k] = p[k];
|
||||
(*pFrame)[2*k+1] = p[k];
|
||||
// (*pFrame)[j+2*k] = p[k];
|
||||
// (*pFrame)[g_width+j+2*k] = p[k];
|
||||
}
|
||||
*pFrame += g_width;
|
||||
}
|
||||
|
||||
*pData += 8;
|
||||
*pDataRemain -= 8;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
for (i=0; i<2; i++) {
|
||||
p[0] = GETPIXEL(pData, 0);
|
||||
p[1] = GETPIXEL(pData, 2);
|
||||
|
||||
for (j=0; j<4; j++) {
|
||||
for (k=0; k<4; k++) {
|
||||
(*pFrame)[k*g_width+j] = p[0];
|
||||
(*pFrame)[k*g_width+j+4] = p[1];
|
||||
}
|
||||
}
|
||||
|
||||
*pFrame += 4*g_width;
|
||||
|
||||
*pData += 4;
|
||||
*pDataRemain -= 4;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 0xe:
|
||||
p[0] = GETPIXEL(pData, 0);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
(*pFrame)[j] = p[0];
|
||||
}
|
||||
|
||||
*pFrame += g_width;
|
||||
}
|
||||
|
||||
*pData += 2;
|
||||
*pDataRemain -= 2;
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case 0xf:
|
||||
p[0] = GETPIXEL(pData, 0);
|
||||
p[1] = GETPIXEL(pData, 1);
|
||||
|
||||
for (i=0; i<8; i++) {
|
||||
for (j=0; j<8; j++) {
|
||||
(*pFrame)[j] = p[(i+j)&1];
|
||||
}
|
||||
*pFrame += g_width;
|
||||
}
|
||||
|
||||
*pData += 4;
|
||||
*pDataRemain -= 4;
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
*pFrame = pDstBak+8;
|
||||
|
||||
+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);
|
||||
|
||||
|
||||
+20
-19
@@ -22,35 +22,36 @@ static int audio_exp_table[256] =
|
||||
|
||||
static int getWord(unsigned char **fin)
|
||||
{
|
||||
int value = ((*fin)[1] << 8) | (*fin)[0];
|
||||
*fin += 2;
|
||||
return value;
|
||||
int value = ((*fin)[1] << 8) | (*fin)[0];
|
||||
*fin += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
static void sendWord(short **fout, int nOffset)
|
||||
{
|
||||
*(*fout)++ = (short)nOffset;
|
||||
*(*fout)++ = nOffset;
|
||||
}
|
||||
|
||||
static void processSwath(short *fout, unsigned char *data, int swath, int *offsets)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<swath; i++) {
|
||||
offsets[i&1] += audio_exp_table[data[i]];
|
||||
sendWord(&fout, offsets[i&1]);
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<swath; i++)
|
||||
{
|
||||
offsets[i&1] += audio_exp_table[data[i]];
|
||||
sendWord(&fout, offsets[i&1]);
|
||||
}
|
||||
}
|
||||
|
||||
void mveaudio_uncompress(short *buffer, unsigned char *data)
|
||||
void mveaudio_uncompress(short *buffer, unsigned char *data, int length)
|
||||
{
|
||||
int nCurOffsets[2];
|
||||
int swath;
|
||||
int nCurOffsets[2];
|
||||
int swath;
|
||||
|
||||
data += 4;
|
||||
swath = getWord(&data) / 2;
|
||||
nCurOffsets[0] = getWord(&data);
|
||||
nCurOffsets[1] = getWord(&data);
|
||||
sendWord(&buffer, nCurOffsets[0]);
|
||||
sendWord(&buffer, nCurOffsets[1]);
|
||||
processSwath(buffer, data, swath, nCurOffsets);
|
||||
data += 4;
|
||||
swath = getWord(&data) / 2;
|
||||
nCurOffsets[0] = getWord(&data);
|
||||
nCurOffsets[1] = getWord(&data);
|
||||
sendWord(&buffer, nCurOffsets[0]);
|
||||
sendWord(&buffer, nCurOffsets[1]);
|
||||
processSwath(buffer, data, swath, nCurOffsets);
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
+112
-125
@@ -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;
|
||||
@@ -60,7 +59,7 @@ typedef struct MVE_AUDIO_T {
|
||||
mve_audio_t *mas; // mve_audio_stream
|
||||
|
||||
// audio decompressor
|
||||
extern void mveaudio_uncompress(short *buffer, unsigned char *data);
|
||||
extern void mveaudio_uncompress(short *buffer, unsigned char *data, int length);
|
||||
|
||||
// video variables
|
||||
int g_width, g_height;
|
||||
@@ -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;
|
||||
@@ -139,9 +137,8 @@ static void mve_timer_start(void)
|
||||
|
||||
static int mve_do_timer_wait(void)
|
||||
{
|
||||
if (!timer_started) {
|
||||
if (!timer_started)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
int nsec = 0;
|
||||
@@ -150,13 +147,11 @@ static int mve_do_timer_wait(void)
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
if (tv.tv_sec > timer_expire.tv_sec) {
|
||||
if (tv.tv_sec > timer_expire.tv_sec)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ( (tv.tv_sec == timer_expire.tv_sec) && (tv.tv_usec >= timer_expire.tv_usec) ) {
|
||||
if ( (tv.tv_sec == timer_expire.tv_sec) && (tv.tv_usec >= timer_expire.tv_usec) )
|
||||
goto end;
|
||||
}
|
||||
|
||||
ts.tv_sec = timer_expire.tv_sec - tv.tv_sec;
|
||||
ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec);
|
||||
@@ -175,24 +170,25 @@ static int mve_do_timer_wait(void)
|
||||
}
|
||||
|
||||
end:
|
||||
timer_expire.tv_usec += micro_frame_delay;
|
||||
timer_expire.tv_usec += micro_frame_delay;
|
||||
|
||||
if (timer_expire.tv_usec > 1000000) {
|
||||
nsec = timer_expire.tv_usec / 1000000;
|
||||
timer_expire.tv_sec += nsec;
|
||||
timer_expire.tv_usec -= nsec * 1000000;
|
||||
}
|
||||
if (timer_expire.tv_usec > 1000000) {
|
||||
nsec = timer_expire.tv_usec / 1000000;
|
||||
timer_expire.tv_sec += nsec;
|
||||
timer_expire.tv_usec -= nsec * 1000000;
|
||||
}
|
||||
#else
|
||||
int tv, ts, ts2;
|
||||
|
||||
tv = timer_get_microseconds();
|
||||
|
||||
if (tv > timer_expire) {
|
||||
if (tv > timer_expire)
|
||||
goto end;
|
||||
}
|
||||
|
||||
ts = timer_expire - tv;
|
||||
|
||||
ts2 = ts/1000;
|
||||
|
||||
Sleep(ts2);
|
||||
|
||||
end:
|
||||
@@ -220,9 +216,8 @@ static void mve_timer_stop()
|
||||
// setup the audio information from the data stream
|
||||
void mve_audio_createbuf(ubyte minor, ubyte *data)
|
||||
{
|
||||
if (audiobuf_created) {
|
||||
if (audiobuf_created)
|
||||
return;
|
||||
}
|
||||
|
||||
// if game sound disabled don't try and play movie audio
|
||||
if (!Sound_enabled) {
|
||||
@@ -230,28 +225,29 @@ 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) );
|
||||
mas = (mve_audio_t *) vm_malloc ( sizeof(mve_audio_t) );
|
||||
memset(mas, 0, sizeof(mve_audio_t));
|
||||
|
||||
mas->format = AL_INVALID;
|
||||
|
||||
flags = mve_get_ushort(data + 2);
|
||||
sample_rate = mve_get_ushort(data + 4);
|
||||
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->channels = (flags & 0x0001) ? 2 : 1;
|
||||
mas->bitsize = (flags & 0x0002) ? 16 : 8;
|
||||
|
||||
mas->sample_rate = sample_rate;
|
||||
|
||||
if (minor > 0) {
|
||||
mve_audio_compressed = flags & 0x0004 ? 1 : 0;
|
||||
} else {
|
||||
if (minor > 0) {
|
||||
mve_audio_compressed = flags & 0x0004 ? 1 : 0;
|
||||
} else {
|
||||
mve_audio_compressed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mas->bitsize == 16) {
|
||||
if (mas->bitsize == 16) {
|
||||
if (mas->channels == 2) {
|
||||
mas->format = AL_FORMAT_STEREO16;
|
||||
} else if (mas->channels == 1) {
|
||||
@@ -280,7 +276,7 @@ void mve_audio_createbuf(ubyte minor, ubyte *data)
|
||||
|
||||
memset(mas->audio_buffer, 0, MVE_AUDIO_BUFFERS * sizeof(ALuint));
|
||||
|
||||
mve_audio_buffer_tail = 0;
|
||||
mve_audio_buffer_tail = 0;
|
||||
|
||||
audiobuf_created = 1;
|
||||
}
|
||||
@@ -292,9 +288,9 @@ void mve_audio_play()
|
||||
ALint status, bqueued;
|
||||
|
||||
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_SOURCE_STATE, &status), return );
|
||||
|
||||
|
||||
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_QUEUED, &bqueued), return );
|
||||
|
||||
|
||||
mve_audio_playing = 1;
|
||||
|
||||
if (status != AL_PLAYING && bqueued > 0) {
|
||||
@@ -306,9 +302,8 @@ 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;
|
||||
}
|
||||
|
||||
ALint p = 0;
|
||||
|
||||
@@ -348,15 +343,13 @@ int mve_audio_data(ubyte major, ubyte *data)
|
||||
|
||||
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_PROCESSED, &bprocessed), return 0 );
|
||||
|
||||
while (bprocessed-- > 2) {
|
||||
while (bprocessed-- > 2)
|
||||
OpenAL_ErrorPrint( alSourceUnqueueBuffers(mas->source_id, 1, &bid) );
|
||||
}
|
||||
|
||||
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_BUFFERS_QUEUED, &bqueued), return 0 );
|
||||
|
||||
if (bqueued == 0) {
|
||||
|
||||
if (bqueued == 0)
|
||||
mprintf(("MVE: Buffer underun (First is normal)\n"));
|
||||
}
|
||||
|
||||
OpenAL_ErrorCheck( alGetSourcei(mas->source_id, AL_SOURCE_STATE, &status), return 0 );
|
||||
|
||||
@@ -369,34 +362,37 @@ int mve_audio_data(ubyte major, ubyte *data)
|
||||
|
||||
/* HACK: +4 mveaudio_uncompress adds 4 more bytes */
|
||||
if (major == 8) {
|
||||
if (mve_audio_compressed) {
|
||||
if (mve_audio_compressed) {
|
||||
nsamp += 4;
|
||||
|
||||
buf = (short *)vm_malloc(nsamp);
|
||||
mveaudio_uncompress(buf, data); /* XXX */
|
||||
mveaudio_uncompress(buf, data, -1); /* XXX */
|
||||
} else {
|
||||
nsamp -= 8;
|
||||
data += 8;
|
||||
|
||||
buf = (short *)vm_malloc(nsamp);
|
||||
memcpy(buf, data, nsamp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buf = (short *)vm_malloc(nsamp);
|
||||
|
||||
memset(buf, 0, nsamp); /* XXX */
|
||||
}
|
||||
|
||||
|
||||
if (!mas->audio_buffer[mve_audio_buffer_tail]) {
|
||||
OpenAL_ErrorCheck( alGenBuffers(1,&mas->audio_buffer[mve_audio_buffer_tail]), { vm_free(buf); return 0; } );
|
||||
}
|
||||
|
||||
OpenAL_ErrorCheck( alBufferData(mas->audio_buffer[mve_audio_buffer_tail], mas->format, buf, nsamp, mas->sample_rate), { vm_free(buf); return 0; } );
|
||||
|
||||
|
||||
OpenAL_ErrorCheck( alSourceQueueBuffers(mas->source_id, 1, &mas->audio_buffer[mve_audio_buffer_tail]), { vm_free(buf); return 0;} );
|
||||
|
||||
//fprintf(stderr,"Queued buffer %d(%d)\n", mve_audio_buftail, mas->audio_buffer[mve_audio_buftail]);
|
||||
|
||||
if (++mve_audio_buffer_tail == MVE_AUDIO_BUFFERS) {
|
||||
if (++mve_audio_buffer_tail == MVE_AUDIO_BUFFERS)
|
||||
mve_audio_buffer_tail = 0;
|
||||
}
|
||||
|
||||
bqueued++;
|
||||
vm_free(buf);
|
||||
@@ -415,15 +411,20 @@ int mve_audio_data(ubyte major, ubyte *data)
|
||||
|
||||
int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
{
|
||||
if (videobuf_created) {
|
||||
if (videobuf_created)
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -441,11 +442,11 @@ int mve_video_createbuf(ubyte minor, ubyte *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (truecolor) {
|
||||
if (truecolor)
|
||||
g_vBackBuf2 = (ushort *)g_vBackBuf1 + (g_width * g_height);
|
||||
} else {
|
||||
else
|
||||
g_vBackBuf2 = (ubyte *)g_vBackBuf1 + (g_width * g_height);
|
||||
}
|
||||
|
||||
memset(g_vBackBuf1, 0, g_width * g_height * 4);
|
||||
|
||||
g_truecolor = truecolor;
|
||||
@@ -454,14 +455,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;
|
||||
} else {
|
||||
scale_by = (float)gr_screen.center_w / (float)g_width;
|
||||
}
|
||||
if (screen_ratio > movie_ratio)
|
||||
scale_by = (float)gr_screen.max_h / (float)g_height;
|
||||
else
|
||||
scale_by = (float)gr_screen.max_w / (float)g_width;
|
||||
|
||||
// don't bother setting anything if we aren't going to need it
|
||||
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
|
||||
@@ -474,12 +474,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 +490,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;
|
||||
@@ -536,26 +507,26 @@ static void mve_convert_and_draw()
|
||||
ubyte r, g, b;
|
||||
ushort bit_16;
|
||||
|
||||
if (g_truecolor) {
|
||||
if (g_truecolor)
|
||||
pSrcs = pixels;
|
||||
} else {
|
||||
else
|
||||
pSrcs8 = pixels8;
|
||||
}
|
||||
|
||||
pDests = pixelbuf;
|
||||
|
||||
if (gr_screen.mode != GR_OPENGL) {
|
||||
if (g_screenWidth > g_width) {
|
||||
if (g_screenWidth > g_width)
|
||||
pDests += ((g_screenWidth - g_width) / 2) / 2;
|
||||
}
|
||||
if (g_screenHeight > g_height) {
|
||||
|
||||
if (g_screenHeight > g_height)
|
||||
pDests += ((g_screenHeight - g_height) / 2) * g_screenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
for (y=0; y<g_height; y++) {
|
||||
for (x = 0; x < g_width; x++) {
|
||||
if (g_truecolor) {
|
||||
Assert( pSrcs != NULL );
|
||||
|
||||
pDests[x] = (1<<15)|*pSrcs;
|
||||
pSrcs++;
|
||||
} else {
|
||||
@@ -604,14 +575,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);
|
||||
}
|
||||
|
||||
@@ -640,9 +621,8 @@ void mve_video_display()
|
||||
|
||||
int mve_video_init(ubyte *data)
|
||||
{
|
||||
if (video_inited) {
|
||||
if (video_inited)
|
||||
return 1;
|
||||
}
|
||||
|
||||
short width, height;
|
||||
|
||||
@@ -688,21 +668,20 @@ int mve_video_init(ubyte *data)
|
||||
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
|
||||
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
|
||||
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
GL_state.Texture.SetWrapS(GL_CLAMP_TO_EDGE);
|
||||
GL_state.Texture.SetWrapT(GL_CLAMP_TO_EDGE);
|
||||
|
||||
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
|
||||
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);
|
||||
|
||||
video_inited = 1;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -722,9 +701,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) {
|
||||
@@ -733,11 +721,10 @@ void mve_video_data(ubyte *data, int len)
|
||||
g_vBackBuf2 = temp;
|
||||
}
|
||||
|
||||
if (g_truecolor) {
|
||||
if (g_truecolor)
|
||||
decodeFrame16((ubyte *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
|
||||
} else {
|
||||
else
|
||||
decodeFrame8((ubyte *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14);
|
||||
}
|
||||
}
|
||||
|
||||
void mve_end_chunk()
|
||||
@@ -766,9 +753,8 @@ void mve_play(MVESTREAM *mve)
|
||||
int init_timer = 0, timer_error = 0;
|
||||
int cont = 1;
|
||||
|
||||
if (!timer_started) {
|
||||
if (!timer_started)
|
||||
mve_timer_start();
|
||||
}
|
||||
|
||||
while (cont && mve_playing && !timer_error) {
|
||||
cont = mve_play_next_chunk(mve);
|
||||
@@ -807,5 +793,6 @@ void mve_shutdown()
|
||||
}
|
||||
|
||||
mve_audio_stop();
|
||||
|
||||
mve_timer_stop();
|
||||
}
|
||||
+63
-182
@@ -9,23 +9,21 @@
|
||||
#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 "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"
|
||||
@@ -44,14 +42,10 @@ static int g_screenX = 0;
|
||||
static int g_screenY = 0;
|
||||
|
||||
static GLuint GLtex = 0;
|
||||
static GLuint ytex = 0;
|
||||
static GLuint utex = 0;
|
||||
static GLuint vtex = 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}};
|
||||
|
||||
// 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);
|
||||
@@ -80,7 +74,7 @@ static int audiofd_fragsize = 0;
|
||||
static longlong videobuf_granulepos = -1;
|
||||
static double videobuf_time = 0;
|
||||
|
||||
static bool use_shaders = true;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility items
|
||||
//
|
||||
@@ -88,8 +82,8 @@ static bool use_shaders = true;
|
||||
// helper; just grab some more compressed bitstream and sync it for page extraction
|
||||
static int OGG_buffer_data(THEORAFILE *movie)
|
||||
{
|
||||
char *buffer = ogg_sync_buffer(&movie->osyncstate, 8192); // Doubled read size to fix choppy audio with high bitrate movies - Valathil
|
||||
int bytes = cfread(buffer, 1, 8192, movie->cfp);
|
||||
char *buffer = ogg_sync_buffer(&movie->osyncstate, 4096);
|
||||
int bytes = cfread(buffer, 1, 4096, movie->cfp);
|
||||
|
||||
ogg_sync_wrote(&movie->osyncstate, bytes);
|
||||
|
||||
@@ -345,103 +339,40 @@ 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())
|
||||
use_shaders = false;
|
||||
glGenTextures(1, &GLtex);
|
||||
|
||||
if(use_shaders) {
|
||||
glGenTextures(1, &ytex);
|
||||
glGenTextures(1, &utex);
|
||||
glGenTextures(1, &vtex);
|
||||
Assert( GLtex != 0 );
|
||||
|
||||
Assert( ytex != 0 );
|
||||
Assert( utex != 0 );
|
||||
Assert( vtex != 0 );
|
||||
|
||||
|
||||
if ( ytex + utex + vtex == 0 ) {
|
||||
nprintf(("MOVIE", "ERROR: Can't create a GL texture"));
|
||||
video_inited = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
int sdr_handle = gr_maybe_create_shader(SDR_TYPE_VIDEO_PROCESS, 0);
|
||||
|
||||
if ( sdr_handle >= 0)
|
||||
opengl_shader_set_current(sdr_handle);
|
||||
else
|
||||
use_shaders = false;
|
||||
}
|
||||
|
||||
if(!use_shaders) {
|
||||
glGenTextures(1, &GLtex);
|
||||
|
||||
Assert( GLtex != 0 );
|
||||
|
||||
if ( GLtex == 0 ) {
|
||||
nprintf(("MOVIE", "ERROR: Can't create a GL texture"));
|
||||
video_inited = 1;
|
||||
return;
|
||||
}
|
||||
if ( GLtex == 0 ) {
|
||||
nprintf(("MOVIE", "ERROR: Can't create a GL texture"));
|
||||
video_inited = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
gr_set_lighting(false, false);
|
||||
GL_state.Texture.DisableAll();
|
||||
|
||||
if(!use_shaders) {
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_texture_target);
|
||||
GL_state.Texture.Enable(GLtex);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RGB8, wp2, hp2, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_texture_target);
|
||||
GL_state.Texture.Enable(GLtex);
|
||||
|
||||
GL_state.SetTextureSource(TEXTURE_SOURCE_DECAL);
|
||||
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
|
||||
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
|
||||
|
||||
if(use_shaders) {
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
GL_state.Texture.SetTarget(GL_texture_target);
|
||||
GL_state.Texture.Enable(ytex);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
|
||||
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_LUMINANCE8, 2048, 2048, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||
GL_state.Texture.SetWrapS(GL_CLAMP_TO_EDGE);
|
||||
GL_state.Texture.SetWrapT(GL_CLAMP_TO_EDGE);
|
||||
|
||||
GL_state.Texture.SetActiveUnit(1);
|
||||
GL_state.Texture.SetTarget(GL_texture_target);
|
||||
GL_state.Texture.Enable(utex);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
|
||||
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RGB8, wp2, hp2, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
// 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);
|
||||
|
||||
GL_state.Texture.SetActiveUnit(2);
|
||||
GL_state.Texture.SetTarget(GL_texture_target);
|
||||
GL_state.Texture.Enable(vtex);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// 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,28 +385,26 @@ 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) {
|
||||
pixelbuf = (ubyte *) vm_malloc_q(g_screenWidth * g_screenHeight * 3);
|
||||
pixelbuf = (ubyte *) vm_malloc_q(g_screenWidth * g_screenHeight * 3);
|
||||
|
||||
if (pixelbuf == NULL) {
|
||||
nprintf(("MOVIE", "ERROR: Can't allocate memory for pixelbuf"));
|
||||
video_inited = 1;
|
||||
return;
|
||||
}
|
||||
memset( pixelbuf, 0, g_screenWidth * g_screenHeight * 3 );
|
||||
if (pixelbuf == NULL) {
|
||||
nprintf(("MOVIE", "ERROR: Can't allocate memory for pixelbuf"));
|
||||
video_inited = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
memset( pixelbuf, 0, g_screenWidth * g_screenHeight * 3 );
|
||||
|
||||
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
|
||||
@@ -485,48 +414,8 @@ static void OGG_video_init(theora_info *tinfo)
|
||||
|
||||
gl_screenU = i2fl(g_screenWidth) / i2fl(wp2);
|
||||
gl_screenV = i2fl(g_screenHeight) / i2fl(hp2);
|
||||
|
||||
if(use_shaders) {
|
||||
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);
|
||||
}
|
||||
|
||||
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."));
|
||||
}
|
||||
|
||||
video_inited = 1;
|
||||
}
|
||||
|
||||
@@ -543,23 +432,12 @@ static void OGG_video_close()
|
||||
}
|
||||
|
||||
GL_state.Texture.Disable();
|
||||
if(use_shaders) {
|
||||
GL_state.Texture.Delete(ytex);
|
||||
GL_state.Texture.Delete(utex);
|
||||
GL_state.Texture.Delete(vtex);
|
||||
glDeleteTextures(1, &ytex);
|
||||
glDeleteTextures(1, &utex);
|
||||
glDeleteTextures(1, &vtex);
|
||||
} else {
|
||||
GL_state.Texture.Delete(GLtex);
|
||||
glDeleteTextures(1, &GLtex);
|
||||
}
|
||||
GL_state.Texture.Delete(GLtex);
|
||||
glDeleteTextures(1, &GLtex);
|
||||
|
||||
opengl_set_texture_target();
|
||||
|
||||
ytex = utex = vtex = 0;
|
||||
GLtex = 0;
|
||||
GL_state.Texture.SetShaderMode(GL_FALSE);
|
||||
opengl_shader_set_current();
|
||||
}
|
||||
|
||||
if (pixelbuf != NULL) {
|
||||
@@ -575,6 +453,7 @@ static void OGG_video_close()
|
||||
g_screenX = 0;
|
||||
g_screenY = 0;
|
||||
|
||||
GLtex = 0;
|
||||
gl_screenYH = 0;
|
||||
gl_screenXW = 0;
|
||||
gl_screenU = 0;
|
||||
@@ -649,29 +528,31 @@ static void convert_YUV_to_RGB(yuv_buffer *yuv)
|
||||
}
|
||||
}
|
||||
|
||||
extern int Mouse_hidden;
|
||||
static void OGG_video_draw(theora_state *tstate)
|
||||
{
|
||||
yuv_buffer yuv;
|
||||
|
||||
theora_decode_YUVout(tstate, &yuv);
|
||||
if(!use_shaders)
|
||||
convert_YUV_to_RGB(&yuv);
|
||||
if (gr_screen.mode == GR_OPENGL) {
|
||||
if(use_shaders) {
|
||||
GL_state.Texture.SetActiveUnit(0);
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, yuv.y_stride, yuv.y_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv.y);
|
||||
GL_state.Texture.SetActiveUnit(1);
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, yuv.uv_stride, yuv.uv_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv.u);
|
||||
GL_state.Texture.SetActiveUnit(2);
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, yuv.uv_stride, yuv.uv_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv.v);
|
||||
} else {
|
||||
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, g_screenWidth, g_screenHeight, GL_BGR, GL_UNSIGNED_BYTE, pixelbuf);
|
||||
}
|
||||
convert_YUV_to_RGB(&yuv);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
if (gr_screen.mode == GR_OPENGL) {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
gr_flip();
|
||||
os_poll();
|
||||
|
||||
@@ -752,7 +633,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];
|
||||
@@ -495,4 +495,7 @@ const char *dds_error_string(int code)
|
||||
default:
|
||||
return "Abort, retry, fail?";
|
||||
}
|
||||
|
||||
//get a warning otherwise
|
||||
return "Abort, retry, fail?";
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+221
-202
@@ -9,32 +9,36 @@
|
||||
|
||||
|
||||
|
||||
#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
|
||||
#define MAX_HULL_PIECES MAX_DEBRIS_PIECES // limit the number of hull debris chunks that can exist.
|
||||
|
||||
// limit the number of hull debris chunks that can exist.
|
||||
//#define MAX_HULL_PIECES 10
|
||||
#define MAX_HULL_PIECES MAX_DEBRIS_PIECES //-WMCD
|
||||
int Num_hull_pieces; // number of hull pieces in existance
|
||||
debris Hull_debris_list; // head of linked list for hull debris chunks, for quick search
|
||||
|
||||
@@ -54,10 +58,13 @@ int Debris_num_submodels = 0;
|
||||
#define MAX_SPEED_SMALL_DEBRIS 200 // maximum velocity of small debris piece
|
||||
#define MAX_SPEED_BIG_DEBRIS 150 // maximum velocity of big debris piece
|
||||
#define MAX_SPEED_CAPITAL_DEBRIS 100 // maximum velocity of capital debris piece
|
||||
//#define DEBRIS_SPEED_DEBUG
|
||||
|
||||
/**
|
||||
* Start the sequence of a piece of debris writhing in unholy agony!!!
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_start_death_roll()
|
||||
//
|
||||
// Start the sequence of a piece of debris writhing in unholy agony!!!
|
||||
//
|
||||
static void debris_start_death_roll(object *debris_obj, debris *debris_p)
|
||||
{
|
||||
if (debris_p->is_hull) {
|
||||
@@ -79,11 +86,14 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
|
||||
}
|
||||
|
||||
debris_obj->flags |= OF_SHOULD_BE_DEAD;
|
||||
// demo_do_flag_dead(OBJ_INDEX(debris_obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* This will get called at the start of each level.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_init()
|
||||
//
|
||||
// This will get called at the start of each level.
|
||||
//
|
||||
void debris_init()
|
||||
{
|
||||
int i;
|
||||
@@ -101,16 +111,13 @@ 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;
|
||||
list_init(&Hull_debris_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page in debris bitmaps at level load
|
||||
*/
|
||||
// Page in debris bitmaps at level load
|
||||
void debris_page_in()
|
||||
{
|
||||
uint i;
|
||||
@@ -144,9 +151,66 @@ void debris_page_in()
|
||||
MONITOR(NumSmallDebrisRend)
|
||||
MONITOR(NumHullDebrisRend)
|
||||
|
||||
/**
|
||||
* Removed the ::DEBRIS_EXPIRE flag, and remove item from ::Hull_debris_list
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_render()
|
||||
//
|
||||
//
|
||||
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
|
||||
void debris_clear_expired_flag(debris *db)
|
||||
{
|
||||
if ( db->flags & DEBRIS_EXPIRE ) {
|
||||
@@ -159,11 +223,12 @@ void debris_clear_expired_flag(debris *db)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the debris object.
|
||||
* This is only ever called via obj_delete(). Do not call directly.
|
||||
* Use debris_start_death_roll() if you want to force a debris piece to die.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_delete()
|
||||
//
|
||||
// Delete the debris object. This is only ever called via obj_delete(). Do not call directly.
|
||||
// Use debris_start_death_roll() if you want to force a debris piece to die.
|
||||
//
|
||||
void debris_delete( object * obj )
|
||||
{
|
||||
int num;
|
||||
@@ -180,15 +245,12 @@ void debris_delete( object * obj )
|
||||
}
|
||||
|
||||
db->flags = 0;
|
||||
db->objnum = -1;
|
||||
Num_debris_pieces--;
|
||||
}
|
||||
|
||||
/**
|
||||
* If debris piece *db is far away from all players, make it go away very soon.
|
||||
* In single player game, delete if MAX_DEBRIS_DIST from player.
|
||||
* In multiplayer game, delete if MAX_DEBRIS_DIST from all players.
|
||||
*/
|
||||
// If debris piece *db is far away from all players, make it go away very soon.
|
||||
// In single player game, delete if MAX_DEBRIS_DIST from player.
|
||||
// In multiplayer game, delete if MAX_DEBRIS_DIST from all players.
|
||||
void maybe_delete_debris(debris *db)
|
||||
{
|
||||
object *objp;
|
||||
@@ -213,16 +275,24 @@ void maybe_delete_debris(debris *db)
|
||||
}
|
||||
}
|
||||
|
||||
// broke debris_move into debris_process_pre and debris_process_post as was done with all
|
||||
// *_move functions on 8/13 by MK and MA.
|
||||
void debris_process_pre( object *objp, float frame_time)
|
||||
{
|
||||
}
|
||||
|
||||
MONITOR(NumSmallDebris)
|
||||
MONITOR(NumHullDebris)
|
||||
|
||||
/**
|
||||
* Do various updates to debris: check if time to die, start fireballs
|
||||
* Maybe delete debris if it's very far away from player.
|
||||
*
|
||||
* @param obj pointer to debris object
|
||||
* @param frame_time time elapsed since last debris_move() called
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_process_post()
|
||||
//
|
||||
// Do various updates to debris: check if time to die, start fireballs
|
||||
//
|
||||
// parameters: obj => pointer to debris object
|
||||
// frame_time => time elapsed since last debris_move() called
|
||||
//
|
||||
// Maybe delete debris if it's very far away from player.
|
||||
void debris_process_post(object * obj, float frame_time)
|
||||
{
|
||||
int i, num;
|
||||
@@ -258,7 +328,10 @@ void debris_process_post(object * obj, float frame_time)
|
||||
return; // If arc_frequency <= 0, this piece has no arcs on it
|
||||
}
|
||||
|
||||
if ( !timestamp_elapsed(db->fire_timeout) && timestamp_elapsed(db->next_fireball)) {
|
||||
if ( !timestamp_elapsed(db->fire_timeout) && timestamp_elapsed(db->next_fireball)) {
|
||||
|
||||
// start the next fireball up in the next 50 - 100 ms
|
||||
//db->next_fireball = timestamp_rand(60,80);
|
||||
|
||||
db->next_fireball = timestamp_rand(db->arc_frequency,db->arc_frequency*2 );
|
||||
db->arc_frequency += 100;
|
||||
@@ -268,14 +341,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;
|
||||
|
||||
@@ -285,7 +352,7 @@ void debris_process_post(object * obj, float frame_time)
|
||||
// Create the spark effects
|
||||
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
|
||||
if ( !timestamp_valid( db->arc_timestamp[i] ) ) {
|
||||
|
||||
//db->arc_timestamp[i] = timestamp_rand(400,1000); // live up to a second
|
||||
db->arc_timestamp[i] = timestamp(lifetime); // live up to a second
|
||||
|
||||
switch( n ) {
|
||||
@@ -337,7 +404,11 @@ void debris_process_post(object * obj, float frame_time)
|
||||
// 0.10 second effect
|
||||
snd_play_3d( &Snds[SND_DEBRIS_ARC_01], &snd_pos, &View_position, obj->radius );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
|
||||
@@ -350,24 +421,21 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the oldest hull debris chunk. Search through the ::Hull_debris_list, which is a list
|
||||
* of all the hull debris chunks.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_find_oldest()
|
||||
//
|
||||
// Locate the oldest hull debris chunk. Search through the Hull_debris_list, which is a list
|
||||
// of all the hull debris chunks.
|
||||
//
|
||||
int debris_find_oldest()
|
||||
{
|
||||
int oldest_index;
|
||||
@@ -389,18 +457,13 @@ int debris_find_oldest()
|
||||
|
||||
#define DEBRIS_ROTVEL_SCALE 5.0f
|
||||
void calc_debris_physics_properties( physics_info *pi, vec3d *min, vec3d *max );
|
||||
|
||||
/**
|
||||
* Create debris from an object
|
||||
*
|
||||
* @param source_obj Source object
|
||||
* @param model_num Model number
|
||||
* @param submodel_num Sub-model number
|
||||
* @param pos Position in vector space
|
||||
* @param exp_center Explosion center in vector space
|
||||
* @param hull_flag Hull flag settings
|
||||
* @param exp_force Explosion force, used to assign velocity to pieces. 1.0f assigns velocity like before. 2.0f assigns twice as much to non-inherited part of velocity
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_create()
|
||||
//
|
||||
// Create debris from an object
|
||||
//
|
||||
// exp_force: Explosion force, used to assign velocity to pieces.
|
||||
// 1.0f assigns velocity like before. 2.0f assigns twice as much to non-inherited part of velocity
|
||||
object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d *pos, vec3d *exp_center, int hull_flag, float exp_force)
|
||||
{
|
||||
int i, n, objnum, parent_objnum;
|
||||
@@ -427,6 +490,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
dist /= 2.0f;
|
||||
}
|
||||
if ( dist > 200.0f ) {
|
||||
//mprintf(( "Not creating debris that is %.1f m away\n", dist ));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -468,11 +532,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 +569,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
|
||||
@@ -517,6 +580,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
|
||||
for (i=0; i<MAX_DEBRIS_ARCS; i++ ) {
|
||||
db->arc_timestamp[i] = timestamp(-1);
|
||||
// vec3d arc_pts[MAX_DEBRIS_ARCS][2]; // The endpoints of each arc
|
||||
}
|
||||
|
||||
if ( db->is_hull ) {
|
||||
@@ -570,6 +634,8 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
obj->net_signature = multi_get_next_network_signature( MULTI_SIG_DEBRIS );
|
||||
}
|
||||
|
||||
// -- No long need shield: bset_shield_strength(obj, 100.0f); // Hey! Set to some meaningful value!
|
||||
|
||||
if (source_obj->type == OBJ_SHIP) {
|
||||
obj->hull_strength = Ships[source_obj->instance].ship_max_hull_strength/8.0f;
|
||||
} else
|
||||
@@ -642,17 +708,26 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
vm_vec_copy_scale(&radial_vel, &to_center, scale );
|
||||
}
|
||||
|
||||
// MK: This next line causes debris pieces to get between 50% and 100% of the parent ship's
|
||||
// velocity. What would be very cool is if the rotational velocity of the parent would become
|
||||
// translational velocity of the debris piece. This would be based on the location of the debris
|
||||
// piece in the parent object.
|
||||
|
||||
// DA: here we need to vel_from_rot = w x to_center, where w is world is unrotated to world coords and offset is the
|
||||
// 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);
|
||||
vm_vec_add2(&obj->phys_info.vel, &vel_from_rotvel);
|
||||
|
||||
// make sure rotational velocity does not get too high
|
||||
// vm_vec_scale_add(&obj->phys_info.vel, &radial_vel, &source_obj->phys_info.vel, frand()/2.0f + 0.5f);
|
||||
// nprintf(("Andsager","object vel from rotvel: %0.2f, %0.2f, %0.2f\n",vel_from_rotvel.x, vel_from_rotvel.y, vel_from_rotvel.z));
|
||||
|
||||
// make sure rotational velocity does not get too high
|
||||
if (radius < 1.0) {
|
||||
radius = 1.0f;
|
||||
}
|
||||
@@ -680,20 +755,29 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
vm_vec_zero(&pi->max_vel); // make so he can't turn on his own VOLITION anymore.
|
||||
vm_vec_zero(&pi->max_rotvel); // make so he can't change speed on his own VOLITION anymore.
|
||||
|
||||
|
||||
// ensure vel is valid
|
||||
Assert( !vm_is_vec_nan(&obj->phys_info.vel) );
|
||||
|
||||
// if ( hull_flag ) {
|
||||
// vm_vec_zero(&pi->vel);
|
||||
// vm_vec_zero(&pi->rotvel);
|
||||
// }
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alas, poor debris_obj got whacked. Fortunately, we know who did it, where and how hard, so we
|
||||
* can do something about it.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_hit()
|
||||
//
|
||||
// Alas, poor debris_obj got whacked. Fortunately, we know who did it, where and how hard, so we
|
||||
// can do something about it.
|
||||
//
|
||||
void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float damage)
|
||||
{
|
||||
debris *debris_p = &Debris[debris_obj->instance];
|
||||
|
||||
|
||||
// Do a little particle spark shower to show we hit
|
||||
{
|
||||
particle_emitter pe;
|
||||
@@ -742,15 +826,16 @@ void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float dama
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See if poor debris object *obj got whacked by evil *other_obj at point *hitpos.
|
||||
* NOTE: debris_hit_info pointer NULL for debris:weapon collision, otherwise debris:ship collision.
|
||||
* @return true if hit, else return false.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_check_collision()
|
||||
//
|
||||
// See if poor debris object *obj got whacked by evil *other_obj at point *hitpos.
|
||||
// NOTE: debris_hit_info pointer NULL for debris:weapon collision, otherwise debris:ship collision.
|
||||
// Return true if hit, else return false.
|
||||
//
|
||||
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 );
|
||||
@@ -764,7 +849,6 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
if ( debris_hit_info == NULL ) {
|
||||
// debris weapon collision
|
||||
Assert( other_obj->type == OBJ_WEAPON );
|
||||
mc.model_instance_num = -1;
|
||||
mc.model_num = Debris[num].model_num; // Fill in the model to check
|
||||
mc.submodel_num = Debris[num].submodel_num;
|
||||
model_clear_instance( mc.model_num );
|
||||
@@ -778,26 +862,22 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
*hitpos = mc.hit_point_world;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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 +898,14 @@ 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_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);
|
||||
|
||||
@@ -839,8 +918,11 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
// first test against the sphere - if this fails then don't do any submodel tests
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
|
||||
SCP_vector<int> submodel_vector;
|
||||
polymodel_instance *pmi;
|
||||
int submodel_list[MAX_ROTATING_SUBMODELS];
|
||||
int num_rotating_submodels = 0;
|
||||
polymodel *pm;
|
||||
|
||||
ship_model_start(ship_obj);
|
||||
|
||||
if (model_collide(&mc)) {
|
||||
|
||||
@@ -849,46 +931,42 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
|
||||
// Do collision the cool new way
|
||||
if ( debris_hit_info->collide_rotate ) {
|
||||
SCP_vector<int>::iterator smv;
|
||||
|
||||
// We collide with the sphere, find the list of rotating submodels and test one at a time
|
||||
model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
|
||||
model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, 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);
|
||||
|
||||
// turn off all rotating submodels and test for collision
|
||||
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
|
||||
pmi->submodel[*smv].collision_checked = true;
|
||||
int i;
|
||||
for (i=0; i<num_rotating_submodels; i++) {
|
||||
pm->submodel[submodel_list[i]].blown_off = 1;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
for (i=0; i<num_rotating_submodels; i++) {
|
||||
// turn on submodel for collision test
|
||||
pmi->submodel[*smv].collision_checked = false;
|
||||
pm->submodel[submodel_list[i]].blown_off = 0;
|
||||
|
||||
// set angles for last frame (need to set to prev to get p0)
|
||||
angles copy_angles = pmi->submodel[*smv].angs;
|
||||
angles copy_angles = pm->submodel[submodel_list[i]].angs;
|
||||
|
||||
// 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);
|
||||
pm->submodel[submodel_list[i]].angs = pm->submodel[submodel_list[i]].sii->prev_angs;
|
||||
world_find_model_point(&p0, &light_obj->last_pos, pm, submodel_list[i], &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);
|
||||
pm->submodel[submodel_list[i]].angs = copy_angles;
|
||||
world_find_model_point(&p1, &light_obj->pos, pm, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
|
||||
|
||||
mc.p0 = &p0;
|
||||
mc.p1 = &p1;
|
||||
// mc.pos = zero // in submodel RF
|
||||
|
||||
mc.orient = &vmd_identity_matrix;
|
||||
mc.submodel_num = *smv;
|
||||
mc.submodel_num = submodel_list[i];
|
||||
|
||||
if ( model_collide(&mc) ) {
|
||||
if ( mc.hit_dist < debris_hit_info->hit_time ) {
|
||||
@@ -896,23 +974,24 @@ 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_find_world_point(&debris_hit_info->hit_pos, &mc.hit_point, mc.model_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_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_find_world_point(&debris_hit_info->light_collision_cm_pos, &int_light_pos, mc.model_num, mc.hit_submodel, &heavy_obj->orient, &zero);
|
||||
}
|
||||
}
|
||||
// Don't look at this submodel again
|
||||
pmi->submodel[*smv].collision_checked = true;
|
||||
pm->submodel[submodel_list[i]].blown_off = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Recover and do usual ship_ship collision, but without rotating submodels
|
||||
@@ -931,7 +1010,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_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
|
||||
@@ -941,16 +1020,17 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ship_model_stop( ship_obj );
|
||||
}
|
||||
|
||||
} else {
|
||||
// Debris is heavier obj
|
||||
mc.model_instance_num = -1;
|
||||
mc.model_num = Debris[num].model_num; // Fill in the model to check
|
||||
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);
|
||||
@@ -1001,9 +1081,11 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the team field for a debris object
|
||||
*/
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// debris_get_team()
|
||||
//
|
||||
// Return the team field for a debris object
|
||||
//
|
||||
int debris_get_team(object *objp)
|
||||
{
|
||||
Assert( objp->type == OBJ_DEBRIS );
|
||||
@@ -1011,9 +1093,7 @@ int debris_get_team(object *objp)
|
||||
return Debris[objp->instance].team;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in debris physics properties when created, specifically mass and moment of inertia
|
||||
*/
|
||||
// fills in debris physics properties when created, specifically mass and moment of inertia
|
||||
void calc_debris_physics_properties( physics_info *pi, vec3d *mins, vec3d *maxs )
|
||||
{
|
||||
float dx, dy, dz, mass;
|
||||
@@ -1037,64 +1117,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
|
||||
@@ -44,7 +42,7 @@ typedef struct debris {
|
||||
vec3d arc_pts[MAX_DEBRIS_ARCS][2]; // The endpoints of each arc
|
||||
int arc_timestamp[MAX_DEBRIS_ARCS]; // When this times out, the spark goes away. -1 is not used
|
||||
int arc_frequency; // Starts at 0, gets bigger
|
||||
int parent_alt_name;
|
||||
char parent_alt_name;
|
||||
float damage_mult;
|
||||
|
||||
} debris;
|
||||
@@ -54,6 +52,7 @@ typedef struct debris {
|
||||
#define DEBRIS_USED (1<<0)
|
||||
#define DEBRIS_EXPIRE (1<<1) // debris can expire (ie hull chunks from small ships)
|
||||
|
||||
|
||||
#define MAX_DEBRIS_PIECES 64
|
||||
|
||||
extern debris Debris[MAX_DEBRIS_PIECES];
|
||||
@@ -63,8 +62,9 @@ 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_pre( object * obj, float frame_time);
|
||||
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 );
|
||||
int debris_check_collision( object * obj, object * other_obj, vec3d * hitpos, collision_info_struct *debris_hit_info=NULL );
|
||||
|
||||
+610
-504
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,406 @@
|
||||
#include "dbugfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
||||
int dbugfile_counters[MAX_COUNTERS];
|
||||
bool dbugfile_init_var = false;
|
||||
|
||||
char dbugfile_filename[512];
|
||||
|
||||
void dbugfile_output(char *buffer)
|
||||
{
|
||||
if(dbugfile_init_var == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FILE *fp = fopen(dbugfile_filename, "a");
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(buffer, sizeof(char) * strlen(buffer), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void dbugfile_init()
|
||||
{
|
||||
// Clear the counters
|
||||
memset(dbugfile_counters, 0, sizeof(int) * MAX_COUNTERS);
|
||||
|
||||
char big_buffer[1000];
|
||||
char temp_buff[512];
|
||||
|
||||
dbugfile_filename[0] = '\0';
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
char path[MAX_PATH];
|
||||
|
||||
GetCurrentDirectory(MAX_PATH, path);
|
||||
|
||||
int path_len = strlen(path);
|
||||
if(path[path_len - 1] != '\\')
|
||||
{
|
||||
path[path_len] = '\\';
|
||||
path[path_len + 1] = '\0';
|
||||
}
|
||||
|
||||
strcpy_s(dbugfile_filename, path);
|
||||
|
||||
#endif
|
||||
|
||||
strcat_s(dbugfile_filename, "DBUG-");
|
||||
strcpy_s(big_buffer, "DBUGFILE Active: ");
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
unsigned long len = 512;
|
||||
GetUserName(temp_buff, &len);
|
||||
|
||||
strcat_s(dbugfile_filename, temp_buff);
|
||||
strcat_s(big_buffer, temp_buff);
|
||||
|
||||
strcat_s(dbugfile_filename, "-");
|
||||
strcat_s(big_buffer, " ");
|
||||
}
|
||||
#endif
|
||||
|
||||
_tzset();
|
||||
|
||||
// Display operating system-style date and time.
|
||||
_strdate( temp_buff);
|
||||
strcat_s(dbugfile_filename, "D(");
|
||||
strcat_s(dbugfile_filename,temp_buff);
|
||||
strcat_s(big_buffer,temp_buff);
|
||||
|
||||
strcat_s(dbugfile_filename, ") T(");
|
||||
strcat_s(big_buffer, " ");
|
||||
|
||||
_strtime( temp_buff);
|
||||
strcat_s(dbugfile_filename,temp_buff);
|
||||
strcat_s(big_buffer,temp_buff);
|
||||
|
||||
strcat_s(dbugfile_filename, ").txt");
|
||||
strcat_s(big_buffer, "\n");
|
||||
|
||||
// Remove invalid slash chars
|
||||
int len = strlen(dbugfile_filename);
|
||||
while(len >= 2)
|
||||
{
|
||||
if(dbugfile_filename[len] == '/' || dbugfile_filename[len] == ':')
|
||||
{
|
||||
dbugfile_filename[len] = '-';
|
||||
}
|
||||
len--;
|
||||
}
|
||||
|
||||
// open file
|
||||
// Uncomment this to see where the file is going
|
||||
//MessageBox(NULL, dbugfile_filename, "das", MB_OK);
|
||||
FILE *fp = fopen(dbugfile_filename, "w");
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(big_buffer, sizeof(char) * strlen(big_buffer), 1, fp);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// detect OS type
|
||||
|
||||
OSVERSIONINFO version_info;
|
||||
version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
|
||||
if(GetVersionEx(&version_info) != false)
|
||||
{
|
||||
char *error = "Error in detecting OS version";
|
||||
char *version = error;
|
||||
|
||||
switch(version_info.dwMajorVersion)
|
||||
{
|
||||
case 4:
|
||||
{
|
||||
if(version_info.dwMinorVersion == 0)
|
||||
{
|
||||
version = "Windows 95";
|
||||
}
|
||||
else if(version_info.dwMinorVersion == 10)
|
||||
{
|
||||
version = "Windows 98";
|
||||
}
|
||||
else if(version_info.dwMinorVersion == 90)
|
||||
{
|
||||
version = "Windows Me";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
if(version_info.dwMinorVersion == 0)
|
||||
{
|
||||
version = "Windows 2000";
|
||||
}
|
||||
else if(version_info.dwMinorVersion == 1)
|
||||
{
|
||||
version = "Windows XP";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *release_type = NULL;
|
||||
#ifdef _DEBUG
|
||||
release_type = "Debug";
|
||||
#else
|
||||
release_type = "Release";
|
||||
#endif
|
||||
sprintf(big_buffer, "OS: %s %s, ", version, release_type);
|
||||
}
|
||||
|
||||
fwrite(big_buffer, sizeof(char) * strlen(big_buffer), 1, fp);
|
||||
|
||||
char exe_name[MAX_PATH];
|
||||
|
||||
GetModuleFileName(NULL, exe_name, MAX_PATH);
|
||||
strcat_s(exe_name, "\n");
|
||||
fwrite(exe_name, sizeof(char) * strlen(exe_name), 1, fp);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
fclose(fp);
|
||||
|
||||
dbugfile_init_var = true;
|
||||
}
|
||||
|
||||
void dbugfile_deinit()
|
||||
{
|
||||
dbugfile_output("Normal end");
|
||||
dbugfile_init_var = false;
|
||||
}
|
||||
|
||||
void dbugfile_sprintf(int line, char *file, const char *format, ...)
|
||||
{
|
||||
if(dbugfile_init_var == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// find last slash (for PC) to crop file path
|
||||
char *ptr = strrchr(file, '\\');
|
||||
|
||||
if(ptr == NULL)
|
||||
{
|
||||
ptr = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
char buffer[1000];
|
||||
int i = sprintf(buffer, "[%s,%4d] ", ptr, line);
|
||||
|
||||
va_list ap;
|
||||
char *p, *sval;
|
||||
long ival;
|
||||
double dval;
|
||||
|
||||
// Add each extra parameter to string
|
||||
va_start(ap, format);
|
||||
|
||||
for(p = (char *) format; *p; p++)
|
||||
{
|
||||
if(*p != '%')
|
||||
{
|
||||
*(buffer + i) = *p;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
switch(*p)
|
||||
{
|
||||
case 'd':
|
||||
{
|
||||
ival = va_arg(ap, int);
|
||||
i += sprintf(buffer+i,"%d", ival);
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
{
|
||||
ival = va_arg(ap, char);
|
||||
buffer[i] = (char) ival;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
{
|
||||
ival = va_arg(ap, int);
|
||||
i += sprintf(buffer+i,"%x", ival);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
{
|
||||
dval = va_arg(ap, double);
|
||||
i += sprintf(buffer+i,"%f", dval);
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
for(sval = va_arg(ap, char *); *sval; sval++)
|
||||
{
|
||||
*(buffer + i++) = *sval;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
i += sprintf(buffer+i,"N/A: %%%c", *p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
i += sprintf(buffer + i, "\n");
|
||||
|
||||
dbugfile_output(buffer);
|
||||
}
|
||||
|
||||
void dbugfile_print_matrix_4x4(int line, char *file, float *matrix, char *text)
|
||||
{
|
||||
if(dbugfile_init_var == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(matrix == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// find last slash (for PC) to crop file path
|
||||
char *ptr = strrchr(file, '\\');
|
||||
|
||||
if(ptr == NULL)
|
||||
{
|
||||
ptr = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if(text == NULL)
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
char buffer[1000];
|
||||
|
||||
sprintf(buffer,"[%s,%4d] Matrix %s:\n"
|
||||
"%f %f %f %f\n"
|
||||
"%f %f %f %f\n"
|
||||
"%f %f %f %f\n"
|
||||
"%f %f %f %f\n",
|
||||
ptr,line, text,
|
||||
matrix[0],
|
||||
matrix[1],
|
||||
matrix[2],
|
||||
matrix[3],
|
||||
matrix[4],
|
||||
matrix[5],
|
||||
matrix[6],
|
||||
matrix[7],
|
||||
matrix[8],
|
||||
matrix[9],
|
||||
matrix[10],
|
||||
matrix[11],
|
||||
matrix[12],
|
||||
matrix[13],
|
||||
matrix[14],
|
||||
matrix[15]);
|
||||
|
||||
dbugfile_output(buffer);
|
||||
}
|
||||
|
||||
void dbugfile_print_matrix_3x3(int line, char *file, float *matrix, char *text)
|
||||
{
|
||||
if(dbugfile_init_var == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(matrix == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// find last slash (for PC) to crop file path
|
||||
char *ptr = strrchr(file, '\\');
|
||||
|
||||
if(ptr == NULL)
|
||||
{
|
||||
ptr = file;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if(text == NULL)
|
||||
{
|
||||
text = "";
|
||||
}
|
||||
|
||||
char buffer[1000];
|
||||
|
||||
sprintf(buffer,"[%s,%4d] Matrix %s:\n"
|
||||
"%f %f %f\n"
|
||||
"%f %f %f\n"
|
||||
"%f %f %f\n",
|
||||
ptr,line, text,
|
||||
matrix[0],
|
||||
matrix[1],
|
||||
matrix[2],
|
||||
matrix[3],
|
||||
matrix[4],
|
||||
matrix[5],
|
||||
matrix[6],
|
||||
matrix[7],
|
||||
matrix[8]);
|
||||
|
||||
dbugfile_output(buffer);
|
||||
}
|
||||
|
||||
void dbugfile_print_counter(int line, char *file, int counter_num, char *string)
|
||||
{
|
||||
char buffer[1000];
|
||||
strcpy_s(buffer, string);
|
||||
strcat_s(buffer, " %d");
|
||||
|
||||
dbugfile_sprintf(line, file, buffer, dbugfile_counters[counter_num]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
#ifndef _DBUGFILE_HEADER_
|
||||
#define _DBUGFILE_HEADER_
|
||||
|
||||
#define MAX_COUNTERS 10
|
||||
|
||||
void dbugfile_init();
|
||||
void dbugfile_deinit();
|
||||
void dbugfile_sprintf(int line, char *file, const char *format, ...);
|
||||
void dbugfile_print_matrix_3x3(int line, char *file, float *matrix, char *text);
|
||||
void dbugfile_print_matrix_4x4(int line, char *file, float *matrix, char *text);
|
||||
void dbugfile_print_counter(int line, char *file, int counter_num, char *string);
|
||||
|
||||
#ifdef DBUGFILE_ACTIVE
|
||||
|
||||
#define DBUGFILE_INIT() dbugfile_init();
|
||||
#define DBUGFILE_DEINIT() dbugfile_deinit();
|
||||
|
||||
#define DBUGFILE_OUTPUT_0(t) dbugfile_sprintf(__LINE__, __FILE__, t);
|
||||
#define DBUGFILE_OUTPUT_1(t,a) dbugfile_sprintf(__LINE__, __FILE__, t,a);
|
||||
#define DBUGFILE_OUTPUT_2(t,a,b) dbugfile_sprintf(__LINE__, __FILE__, t,a,b);
|
||||
#define DBUGFILE_OUTPUT_3(t,a,b,c) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c);
|
||||
#define DBUGFILE_OUTPUT_4(t,a,b,c,d) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d);
|
||||
#define DBUGFILE_OUTPUT_5(t,a,b,c,d,e) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d,e);
|
||||
#define DBUGFILE_OUTPUT_6(t,a,b,c,d,e,f) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d,e,f);
|
||||
#define DBUGFILE_OUTPUT_7(t,a,b,c,d,e,f,g) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d,e,f,g);
|
||||
#define DBUGFILE_OUTPUT_8(t,a,b,c,d,e,f,g,h) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d,e,f,g,h);
|
||||
#define DBUGFILE_OUTPUT_9(t,a,b,c,d,e,f,g,h,i) dbugfile_sprintf(__LINE__, __FILE__, t,a,b,c,d,e,f,g,h,i);
|
||||
|
||||
#define DBUGFILE_OUTPUT_MATRIX_3X3(m,t) dbugfile_print_matrix_3x3(__LINE__, __FILE__, m,t);
|
||||
#define DBUGFILE_OUTPUT_MATRIX_4X4(m,t) dbugfile_print_matrix_4x4(__LINE__, __FILE__, m,t);
|
||||
|
||||
extern int dbugfile_counters[MAX_COUNTERS];
|
||||
#define DBUGFILE_INC_COUNTER(n) if(n < MAX_COUNTERS) dbugfile_counters[n]++;
|
||||
#define DBUGFILE_DEC_COUNTER(n) if(n < MAX_COUNTERS) dbugfile_counters[n]--;
|
||||
|
||||
#define DBUGFILE_OUTPUT_COUNTER(n,s) dbugfile_print_counter(__LINE__, __FILE__, n, s);
|
||||
|
||||
#else
|
||||
|
||||
#define DBUGFILE_INIT() ;
|
||||
#define DBUGFILE_DEINIT() ;
|
||||
|
||||
#define DBUGFILE_OUTPUT_0(t) ;
|
||||
#define DBUGFILE_OUTPUT_1(t,a) ;
|
||||
#define DBUGFILE_OUTPUT_2(t,a,b) ;
|
||||
#define DBUGFILE_OUTPUT_3(t,a,b,c) ;
|
||||
#define DBUGFILE_OUTPUT_4(t,a,b,c,d) ;
|
||||
#define DBUGFILE_OUTPUT_5(t,a,b,c,d,e) ;
|
||||
#define DBUGFILE_OUTPUT_6(t,a,b,c,d,e,f) ;
|
||||
#define DBUGFILE_OUTPUT_7(t,a,b,c,d,e,f,g) ;
|
||||
#define DBUGFILE_OUTPUT_8(t,a,b,c,d,e,f,g,h) ;
|
||||
#define DBUGFILE_OUTPUT_9(t,a,b,c,d,e,f,g,h,i) ;
|
||||
|
||||
#define DBUGFILE_OUTPUT_MATRIX_3X3(m,t) ;
|
||||
#define DBUGFILE_OUTPUT_MATRIX_4X4(m,t) ;
|
||||
|
||||
#define DBUGFILE_INC_COUNTER(n) ;
|
||||
#define DBUGFILE_DEC_COUNTER(n) ;
|
||||
|
||||
#define DBUGFILE_OUTPUT_COUNTER(n,s) ;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 int colour - colour index (>=0)
|
||||
* @param int xpos - x position to start bar on
|
||||
* @param int xwidth - width of bar
|
||||
* @param int 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 void (*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,38 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
#define TIMERBAR_SET_DRAW_FUNC(f) if (Cmdline_timerbar) timerbar_set_draw_func(f);
|
||||
#define TIMERBAR_START_FRAME() if (Cmdline_timerbar) timerbar_start_frame();
|
||||
#define TIMERBAR_END_FRAME() if (Cmdline_timerbar) timerbar_end_frame();
|
||||
#define TIMERBAR_SWITCH_TYPE(n) if (Cmdline_timerbar) timerbar_switch_type(n);
|
||||
|
||||
#define TIMERBAR_PUSH(v) if (Cmdline_timerbar) timerbar_push(v);
|
||||
#define TIMERBAR_POP() if (Cmdline_timerbar) timerbar_pop();
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,129 @@
|
||||
//header file for making decals-Bobboau
|
||||
|
||||
|
||||
#ifndef _DECAL_H
|
||||
#define _DECAL_H
|
||||
|
||||
#include "object/object.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
//#include "ship/ship.h"
|
||||
|
||||
#ifdef ENABLE_DECALS
|
||||
|
||||
#define MAX_DECAL_POLY 40
|
||||
#define MAX_DECAL_POLY_POINT 10
|
||||
#define MAX_DECAL_DEFPOINTS 10000
|
||||
#define MAX_DECAL_POINT 10
|
||||
#define MAX_SHIP_DECALS 25
|
||||
#define MAX_GLOBAL_DECAL_POLYS 11000
|
||||
#define QUICKFIND_SUBDIVISION 100
|
||||
#define QUICKFIND_SEGMENT_LENGTH (MAX_GLOBAL_DECAL_POLYS/QUICKFIND_SUBDIVISION)
|
||||
#define MAX_GLOBAL_DECALS 5000
|
||||
|
||||
#define DP_EOF 0
|
||||
#define DP_DEFPOINTS 1
|
||||
#define DP_FLATPOLY 2
|
||||
#define DP_TMAPPOLY 3
|
||||
#define DP_SORTNORM 4
|
||||
#define DP_BOUNDBOX 5
|
||||
|
||||
#endif // ENABLE_DECALS
|
||||
|
||||
struct decal;
|
||||
struct decal_list;
|
||||
struct decal_list_controle;
|
||||
|
||||
struct decal_poly{
|
||||
vec3d norm[3];
|
||||
vertex point[3];
|
||||
decal_poly *next;
|
||||
decal* parent;
|
||||
int idx;
|
||||
};
|
||||
|
||||
struct decal{
|
||||
int n_poly;
|
||||
int timestamp; //when this decal was created
|
||||
int burn_time; //how long it takes for the glow texture to fade
|
||||
int vertex_buffer_start; //were is the start of this decal's polys in the vertex buffer
|
||||
decal_poly* poly;
|
||||
decal_poly* add_poly();
|
||||
decal_poly* get_last_poly();
|
||||
void remove_last_poly();
|
||||
decal_list_controle *parent;
|
||||
};
|
||||
|
||||
struct decal_list{
|
||||
decal dec;
|
||||
decal_list *next;
|
||||
};
|
||||
|
||||
struct decal_item{
|
||||
decal_list dec;
|
||||
bool used;
|
||||
};
|
||||
|
||||
struct decal_list_controle{
|
||||
int n_decals;
|
||||
int buffer;
|
||||
int texture;
|
||||
int n_poly;
|
||||
int burn_texture;
|
||||
int glow_texture;
|
||||
bool modifyed;
|
||||
decal_list *d_list;
|
||||
decal_list *end;
|
||||
decal_list *add_new();
|
||||
void trim();
|
||||
void clear();
|
||||
~decal_list_controle();
|
||||
decal_list_controle();
|
||||
};
|
||||
|
||||
struct decal_system{
|
||||
decal_list_controle *decals;
|
||||
int n_decal_textures;
|
||||
bool decals_modified;
|
||||
int max_decals;
|
||||
decal_system():decals(NULL),n_decal_textures(0),decals_modified(false){};
|
||||
};
|
||||
|
||||
|
||||
//this is used to give all the data to the generation data to the functions that make them
|
||||
|
||||
struct decal_point{
|
||||
vec3d pnt;
|
||||
matrix orient;
|
||||
float radius;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_DECALS
|
||||
|
||||
int decal_create(object * obj, decal_point *point, int subobject, int texture, int backfaced_texture = -1, int glow_texture = -1, int burn_texture = -1, int burn_time = 1000);//makes the decal
|
||||
|
||||
int decal_create_simple(object * obj, decal_point *point, int texture);//makes a simple non-clipped decal
|
||||
|
||||
void decal_render_all(object * obj); //renders all decals
|
||||
|
||||
int decal_create_sub(void *model_ptr);
|
||||
|
||||
void clear_decals(decal_system *system);
|
||||
|
||||
void init_decals();
|
||||
|
||||
#else // ENABLE_DECALS
|
||||
|
||||
inline int decal_create(object * obj, decal_point *point, int subobject, int texture, int backfaced_texture = -1, int glow_texture = -1, int burn_texture = -1, int burn_time = 1000)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define decal_create_simple(a, b, c) (0)
|
||||
#define decal_render_all(a)
|
||||
#define decal_create_sub(a) (0);
|
||||
#define clear_decals(a)
|
||||
#define init_decals()
|
||||
|
||||
#endif // ENABLE_DECALS
|
||||
|
||||
#endif // _DECAL_H
|
||||
@@ -0,0 +1,974 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "demo/demo.h"
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "freespace2/freespace.h"
|
||||
#include "object/object.h"
|
||||
#include "io/timer.h"
|
||||
#include "gamesequence/gamesequence.h"
|
||||
#include "mission/missionmessage.h"
|
||||
#include "mission/missionparse.h"
|
||||
#include "ship/shipfx.h"
|
||||
#include "ship/shiphit.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO DEFINES/VARS
|
||||
//
|
||||
|
||||
CFILE *Demo_file = NULL;
|
||||
|
||||
// how often we dump
|
||||
#define DEMO_DEFAULT_FPS 15
|
||||
int Demo_fps = 1000 / DEMO_DEFAULT_FPS;
|
||||
|
||||
// timestamp for frame dumping
|
||||
int Demo_stamp = -1;
|
||||
|
||||
// missiontime
|
||||
float Demo_missiontime = 0.0f;
|
||||
|
||||
// buffer for reading and writing demo stuff
|
||||
#define DEMO_BUF_SIZE 32768
|
||||
char *Demo_buf = NULL;
|
||||
int Demo_buf_pos = 0;
|
||||
|
||||
// # of events posted for this frame
|
||||
int Demo_frame_events = 0;
|
||||
|
||||
// current offset into the demo file - only used for playback
|
||||
int Demo_cur_offset = -1;
|
||||
|
||||
// demo version #
|
||||
#define DEMO_VERSION 2
|
||||
|
||||
// an error reading or writing the demo file
|
||||
int Demo_error = DEMO_ERROR_NONE;
|
||||
|
||||
// all strings read out of the demo file must be no longer than this
|
||||
#define DEMO_STRING_LEN 255
|
||||
|
||||
// macros
|
||||
#define DEMO_DATA_FRAME() do { \
|
||||
if(Demo_file == NULL){\
|
||||
Int3();\
|
||||
DEMO_ERROR(DEMO_ERROR_GENERAL);\
|
||||
break;\
|
||||
}\
|
||||
if(Game_mode & GM_DEMO_RECORD){\
|
||||
if(Demo_buf_pos == 0) {\
|
||||
Int3();\
|
||||
break;\
|
||||
}\
|
||||
if(Demo_frame_events <= 0){\
|
||||
break;\
|
||||
}\
|
||||
if(!cfwrite_ushort((ushort)Demo_buf_pos, Demo_file)){\
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_SPACE);\
|
||||
break;\
|
||||
}\
|
||||
if(!cfwrite(Demo_buf, Demo_buf_pos, 1, Demo_file)){\
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_SPACE);\
|
||||
break;\
|
||||
}\
|
||||
} else if(Game_mode & GM_DEMO_PLAYBACK){\
|
||||
Demo_buf_pos = (int)cfread_ushort(Demo_file);\
|
||||
if(!cfread(Demo_buf, Demo_buf_pos, 1, Demo_file)){\
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
} while(0)
|
||||
#define DEMO_DATA(vl, vl_size) do { if(Demo_buf == NULL){ DEMO_ERROR(DEMO_ERROR_GENERAL); break; } if((Demo_buf_pos + vl_size) >= DEMO_BUF_SIZE){ Int3(); DEMO_ERROR(DEMO_ERROR_FRAMESIZE); break; } if(Game_mode & GM_DEMO_RECORD){ memcpy(Demo_buf + Demo_buf_pos, &vl, vl_size); } else if(Game_mode & GM_DEMO_PLAYBACK){ memcpy(&vl, Demo_buf + Demo_buf_pos, vl_size); } Demo_buf_pos += vl_size; } while(0)
|
||||
#define DEMO_INT(vl) do { DEMO_DATA(vl, sizeof(int)); } while(0)
|
||||
#define DEMO_UINT(vl) do { DEMO_DATA(vl, sizeof(uint)); } while(0)
|
||||
#define DEMO_SHORT(vl) do { DEMO_DATA(vl, sizeof(short)); } while(0)
|
||||
#define DEMO_USHORT(vl) do { DEMO_DATA(vl, sizeof(ushort)); } while(0)
|
||||
#define DEMO_BYTE(vl) do { DEMO_DATA(vl, sizeof(char)); } while(0)
|
||||
#define DEMO_UBYTE(vl) do { DEMO_DATA(vl, sizeof(ubyte)); } while(0)
|
||||
#define DEMO_FLOAT(vl) do { DEMO_DATA(vl, sizeof(float)); } while(0)
|
||||
#define DEMO_VECTOR(vl) do { DEMO_DATA(vl, sizeof(vec3d)); } while(0)
|
||||
#define DEMO_MATRIX(vl) do { DEMO_DATA(vl, sizeof(matrix)); } while(0)
|
||||
#define DEMO_STRING(vl) do { int stlen; if(Game_mode & GM_DEMO_RECORD){ stlen = strlen(vl); if(stlen <= 0){ break; } DEMO_DATA(stlen, sizeof(ushort)); DEMO_DATA(*vl, strlen(vl)); } else { ushort len = 0; DEMO_USHORT(len); DEMO_DATA(*vl, len); vl[len] = '\0'; } } while(0)
|
||||
|
||||
// demo events types
|
||||
#define DE_DUMP 1 // standard object dump
|
||||
#define DE_TRAILER 2 // end of demo trailer
|
||||
#define DE_PRIMARY 3 // primary weapon fired
|
||||
#define DE_UNIQUE_MESSAGE 4 // unique hud message
|
||||
#define DE_BUILTIN_MESSAGE 5 // builtin hud message
|
||||
#define DE_OBJ_CREATE 6 // object create message
|
||||
#define DE_OBJ_WARPIN 7 // ship warpin
|
||||
#define DE_OBJ_WARPOUT 8 // ship warpout
|
||||
#define DE_OBJ_DEPARTED 9 // ship departed
|
||||
#define DE_SHIP_KILL 10 // ship kill
|
||||
|
||||
// call this when posting an error
|
||||
#define DEMO_ERROR(er) do { Demo_error = er; Int3(); } while(0)
|
||||
|
||||
int Demo_make = 0;
|
||||
DCF(demo, "")
|
||||
{
|
||||
Demo_make = !Demo_make;
|
||||
if(Demo_make){
|
||||
dc_printf("Demo will be recorded\n");
|
||||
} else {
|
||||
dc_printf("Demo will NOT be recorded\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO FORWARD DECLARATIONS
|
||||
//
|
||||
|
||||
// write demo header
|
||||
int demo_write_header();
|
||||
|
||||
// read the demo header
|
||||
int demo_read_header();
|
||||
|
||||
// write the demo trailer
|
||||
void demo_write_trailer();
|
||||
|
||||
// do a recording frame
|
||||
void demo_do_recording_frame_start();
|
||||
|
||||
// do a recording frame
|
||||
void demo_do_recording_frame_end();
|
||||
|
||||
// do a playback frame
|
||||
void demo_do_playback_frame();
|
||||
|
||||
// seek through the demo file to the proper location
|
||||
// return 0 on error, 1 on success/continue, 2 if the demo is done
|
||||
int demo_playback_seek();
|
||||
|
||||
// scan through a read in frame of data and apply everything necessary. returns true if the trailer (end of demo) was found
|
||||
int demo_playback_seek_sub(int frame_size);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO FUNCTIONS
|
||||
//
|
||||
|
||||
// do frame for the demo - playback and recording, returns 0 if errors were encountered during frame processing
|
||||
int demo_do_frame_start()
|
||||
{
|
||||
#ifndef DEMO_SYSTEM
|
||||
return 1;
|
||||
#else
|
||||
// if we're not doing any demo stuff
|
||||
if(!(Game_mode & GM_DEMO)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// bad
|
||||
if(Demo_file == NULL){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure we're not trying to record and playback at the same time
|
||||
Assert( ((Game_mode & GM_DEMO_RECORD) && !(Game_mode & GM_DEMO_PLAYBACK)) || (!(Game_mode & GM_DEMO_RECORD) && (Game_mode & GM_DEMO_PLAYBACK)) );
|
||||
|
||||
// recording
|
||||
if(Game_mode & GM_DEMO_RECORD){
|
||||
demo_do_recording_frame_start();
|
||||
} else {
|
||||
demo_do_playback_frame();
|
||||
}
|
||||
|
||||
// bad bad bad, get mwa
|
||||
if(Demo_error){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// continue
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// do frame for the demo - playback and recording, returns 0 if errors were encountered during frame processing
|
||||
int demo_do_frame_end()
|
||||
{
|
||||
#ifndef DEMO_SYSTEM
|
||||
return 1;
|
||||
#else
|
||||
// if we're not doing any demo stuff
|
||||
if(!(Game_mode & GM_DEMO)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// bad
|
||||
if(Demo_file == NULL){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure we're not trying to record and playback at the same time
|
||||
Assert( ((Game_mode & GM_DEMO_RECORD) && !(Game_mode & GM_DEMO_PLAYBACK)) || (!(Game_mode & GM_DEMO_RECORD) && (Game_mode & GM_DEMO_PLAYBACK)) );
|
||||
|
||||
// recording. there's nothing to do here for playback
|
||||
if(Game_mode & GM_DEMO_RECORD){
|
||||
demo_do_recording_frame_end();
|
||||
}
|
||||
|
||||
// bad bad bad, get mwa
|
||||
if(Demo_error){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// continue
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize a demo for recording
|
||||
// NOTE : call this after loading the mission and going through the briefing, but _before_ physically moving into the mission
|
||||
int demo_start_record(char *file)
|
||||
{
|
||||
#ifndef DEMO_SYSTEM
|
||||
return 0;
|
||||
#else
|
||||
char full_name[MAX_FILENAME_LEN] = "";
|
||||
|
||||
// try and allocate the buffer
|
||||
Demo_buf = (char*)vm_malloc(DEMO_BUF_SIZE);
|
||||
if(Demo_buf == NULL){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// open the outfile
|
||||
strcpy_s(full_name, file);
|
||||
cf_add_ext(full_name, ".fsd");
|
||||
Demo_file = cfopen(full_name, "wb", CFILE_NORMAL, CF_TYPE_DEMOS);
|
||||
if(Demo_file == NULL){
|
||||
Int3();
|
||||
Demo_error = DEMO_ERROR_DISK_ACCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no errors
|
||||
Demo_error = DEMO_ERROR_NONE;
|
||||
|
||||
// write the header
|
||||
if(!demo_write_header()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// flag demo mode
|
||||
Game_mode |= GM_DEMO_RECORD;
|
||||
|
||||
// no events yet
|
||||
Demo_frame_events = 0;
|
||||
|
||||
// success
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize a demo for playback - calling this will load up the demo file and move the player into the playback state
|
||||
int demo_start_playback(char *file)
|
||||
{
|
||||
#ifndef DEMO_SYSTEM
|
||||
return 0;
|
||||
#else
|
||||
char full_name[MAX_FILENAME_LEN] = "";
|
||||
|
||||
// try and allocate the buffer
|
||||
Demo_buf = (char*)vm_malloc(DEMO_BUF_SIZE);
|
||||
if(Demo_buf == NULL){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// open the outfile
|
||||
strcpy_s(full_name, file);
|
||||
cf_add_ext(full_name, ".fsd");
|
||||
Demo_file = cfopen(full_name, "rb", CFILE_NORMAL, CF_TYPE_DEMOS);
|
||||
if(Demo_file == NULL){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no errors
|
||||
Demo_error = DEMO_ERROR_NONE;
|
||||
|
||||
// read the header
|
||||
Demo_cur_offset = -1;
|
||||
if(!demo_read_header()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// flag demo mode
|
||||
Game_mode |= GM_DEMO_PLAYBACK;
|
||||
|
||||
// everything is cool, so jump into the mission
|
||||
gameseq_post_event(GS_EVENT_ENTER_GAME);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// finish the demo
|
||||
void demo_close()
|
||||
{
|
||||
#ifdef DEMO_SYSTEM
|
||||
// if we're recording, write the trailer
|
||||
if(Game_mode & GM_DEMO_RECORD){
|
||||
demo_write_trailer();
|
||||
}
|
||||
|
||||
// close the demo file
|
||||
if(Demo_file != NULL){
|
||||
cfclose(Demo_file);
|
||||
Demo_file = NULL;
|
||||
}
|
||||
|
||||
// free the buffer
|
||||
if(Demo_buf != NULL){
|
||||
vm_free(Demo_buf);
|
||||
Demo_buf = NULL;
|
||||
}
|
||||
|
||||
// if we're playing back, go back to the main hall
|
||||
if(Game_mode & GM_DEMO_PLAYBACK){
|
||||
gameseq_post_event(GS_EVENT_MAIN_MENU);
|
||||
}
|
||||
|
||||
// unflag demo mode
|
||||
Game_mode &= ~(GM_DEMO_RECORD | GM_DEMO_PLAYBACK);
|
||||
#endif
|
||||
}
|
||||
|
||||
// if we should run the simulation for this object, or let the demo system handle it
|
||||
int demo_should_sim(object *objp)
|
||||
{
|
||||
#ifndef DEMO_SYSTEM
|
||||
return 1;
|
||||
#else
|
||||
// always sim stuff in non-demo mode
|
||||
if(!(Game_mode & GM_DEMO)){
|
||||
return 1;
|
||||
}
|
||||
|
||||
// don't sim ships or missiles
|
||||
if((objp->type == OBJ_SHIP) || ((objp->type == OBJ_WEAPON) && (objp->instance >= 0) && (Weapon_info[Weapons[objp->instance].weapon_info_index].subtype == WP_MISSILE))){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sim everything else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO RECORDING FUNCTIONS
|
||||
//
|
||||
|
||||
// write demo header
|
||||
int demo_write_header()
|
||||
{
|
||||
uint chksum;
|
||||
char *full_name;
|
||||
|
||||
// write demo version #
|
||||
if(!cfwrite_int(DEMO_VERSION, Demo_file)){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// write mission filename
|
||||
if(!cfwrite_string_len(Game_current_mission_filename, Demo_file)){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// write mission checksum
|
||||
full_name = cf_add_ext(Game_current_mission_filename, FS_MISSION_FILE_EXT);
|
||||
cf_chksum_long(full_name, &chksum);
|
||||
if(!cfwrite_int(chksum, Demo_file)){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// success
|
||||
return 1;
|
||||
}
|
||||
|
||||
// write the demo trailer
|
||||
void demo_write_trailer()
|
||||
{
|
||||
// start a new chunk
|
||||
demo_do_recording_frame_start();
|
||||
|
||||
// trailer event
|
||||
ubyte frame_type = DE_TRAILER;
|
||||
DEMO_UBYTE(frame_type);
|
||||
|
||||
// 1 event
|
||||
Demo_frame_events++;
|
||||
|
||||
// write frame data to disk
|
||||
DEMO_DATA_FRAME();
|
||||
}
|
||||
|
||||
// start recording frame
|
||||
void demo_do_recording_frame_start()
|
||||
{
|
||||
// if we're not physically doing the mission
|
||||
if(gameseq_get_state() != GS_STATE_GAME_PLAY){
|
||||
return;
|
||||
}
|
||||
|
||||
// add in frametime
|
||||
Demo_missiontime += flFrametime;
|
||||
|
||||
// clear the buffer, set no events, and write the header
|
||||
Demo_buf_pos = 0;
|
||||
Demo_frame_events = 0;
|
||||
|
||||
// missiontime
|
||||
float fl_time = f2fl(Missiontime);
|
||||
DEMO_FLOAT(fl_time);
|
||||
}
|
||||
|
||||
// end recording frame
|
||||
void demo_do_recording_frame_end()
|
||||
{
|
||||
// if we're not physically doing the mission
|
||||
if(gameseq_get_state() != GS_STATE_GAME_PLAY){
|
||||
return;
|
||||
}
|
||||
|
||||
// if its time to dump objects (the last thing we might dump per frame)
|
||||
if((Demo_stamp == -1) || timestamp_elapsed(Demo_stamp)){
|
||||
// post an object dump event
|
||||
demo_POST_object_dump();
|
||||
|
||||
// reset the stamp
|
||||
Demo_stamp = timestamp(Demo_fps);
|
||||
}
|
||||
|
||||
// write all accumulated frame data to disk if necessary
|
||||
DEMO_DATA_FRAME();
|
||||
}
|
||||
|
||||
// post an object dump event
|
||||
void demo_POST_object_dump()
|
||||
{
|
||||
ship_obj *sobjp;
|
||||
object *objp;
|
||||
ushort obj_count;
|
||||
ubyte team;
|
||||
|
||||
// object dump event
|
||||
ubyte event_type = DE_DUMP;
|
||||
DEMO_UBYTE(event_type);
|
||||
|
||||
// go through the ship list and count
|
||||
obj_count = 0;
|
||||
for ( sobjp = GET_FIRST(&Ship_obj_list); sobjp !=END_OF_LIST(&Ship_obj_list); sobjp = GET_NEXT(sobjp) ){
|
||||
// object pointer
|
||||
if(sobjp->objnum < 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
obj_count++;
|
||||
}
|
||||
|
||||
// write out the object count
|
||||
DEMO_USHORT(obj_count);
|
||||
|
||||
// go through the ship list and dump necessary stuff
|
||||
for ( sobjp = GET_FIRST(&Ship_obj_list); sobjp !=END_OF_LIST(&Ship_obj_list); sobjp = GET_NEXT(sobjp) ){
|
||||
// object pointer
|
||||
if(sobjp->objnum < 0){
|
||||
continue;
|
||||
}
|
||||
objp = &Objects[sobjp->objnum];
|
||||
|
||||
// just ships for now
|
||||
DEMO_INT(objp->signature);
|
||||
DEMO_VECTOR(objp->pos);
|
||||
DEMO_MATRIX(objp->orient);
|
||||
DEMO_FLOAT(objp->phys_info.forward_thrust);
|
||||
team = (ubyte)Ships[objp->instance].team;
|
||||
DEMO_UBYTE(team);
|
||||
DEMO_INT(Ships[objp->instance].flags);
|
||||
}
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a primary fired event
|
||||
void demo_POST_primary_fired(object *objp, int banks, int linked)
|
||||
{
|
||||
ubyte fire_info = 0;
|
||||
|
||||
// object dump event
|
||||
ubyte event_type = DE_PRIMARY;
|
||||
DEMO_UBYTE(event_type);
|
||||
|
||||
// object signature
|
||||
DEMO_INT(objp->signature);
|
||||
|
||||
// get fire info
|
||||
fire_info = (ubyte)banks;
|
||||
fire_info &= ~(1<<7);
|
||||
if(linked){
|
||||
fire_info |= (1<<7);
|
||||
}
|
||||
DEMO_UBYTE(fire_info);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a unique message
|
||||
void demo_POST_unique_message(char *id, char *who_from, int m_source, int priority)
|
||||
{
|
||||
// sanity
|
||||
if((id == NULL) || (who_from == NULL) || (strlen(id) <= 0) || (strlen(who_from) <= 0)){
|
||||
return;
|
||||
}
|
||||
|
||||
// write it
|
||||
ubyte event = DE_UNIQUE_MESSAGE;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_STRING(id);
|
||||
DEMO_STRING(who_from);
|
||||
DEMO_INT(m_source);
|
||||
DEMO_INT(priority);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a builtin message
|
||||
void demo_POST_builtin_message(int type, ship *shipp, int priority, int timing)
|
||||
{
|
||||
int sig = 0;
|
||||
|
||||
// write it
|
||||
ubyte event = DE_BUILTIN_MESSAGE;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_INT(type);
|
||||
if(shipp == NULL){
|
||||
sig = -1;
|
||||
} else if(shipp->objnum >= 0){
|
||||
sig = Objects[shipp->objnum].signature;
|
||||
}
|
||||
DEMO_INT(sig);
|
||||
DEMO_INT(priority);
|
||||
DEMO_INT(timing);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post an object create message
|
||||
void demo_POST_obj_create(char *pobj_name, int signature)
|
||||
{
|
||||
// write it
|
||||
ubyte event = DE_OBJ_CREATE;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_STRING(pobj_name);
|
||||
DEMO_INT(signature);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a warpin event
|
||||
void demo_POST_warpin(int signature, int ship_flags)
|
||||
{
|
||||
// write it
|
||||
ubyte event = DE_OBJ_WARPIN;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_INT(signature);
|
||||
DEMO_INT(ship_flags);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a warpout event
|
||||
void demo_POST_warpout(int signature, int ship_flags)
|
||||
{
|
||||
// write it
|
||||
ubyte event = DE_OBJ_WARPOUT;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_INT(signature);
|
||||
DEMO_INT(ship_flags);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a departed event
|
||||
void demo_POST_departed(int signature, int ship_flags)
|
||||
{
|
||||
// write it
|
||||
ubyte event = DE_OBJ_DEPARTED;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_INT(signature);
|
||||
DEMO_INT(ship_flags);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
// post a ship kill event
|
||||
void demo_POST_ship_kill(object *objp)
|
||||
{
|
||||
// write it
|
||||
ubyte event = DE_SHIP_KILL;
|
||||
DEMO_UBYTE(event);
|
||||
DEMO_INT(objp->signature);
|
||||
|
||||
// up the event count
|
||||
Demo_frame_events++;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO PLAYBACK FUNCTIONS
|
||||
//
|
||||
|
||||
// read the demo header
|
||||
int demo_read_header()
|
||||
{
|
||||
int version;
|
||||
uint file_checksum, my_checksum;
|
||||
char *full_name;
|
||||
|
||||
// read the version #
|
||||
version = cfread_int(Demo_file);
|
||||
if(version != DEMO_VERSION){
|
||||
DEMO_ERROR(DEMO_ERROR_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read mission filename
|
||||
cfread_string_len(Game_current_mission_filename, MAX_FILENAME_LEN, Demo_file);
|
||||
|
||||
// get mission checksum
|
||||
file_checksum = cfread_int(Demo_file);
|
||||
full_name = cf_add_ext(Game_current_mission_filename, FS_MISSION_FILE_EXT);
|
||||
if(!cf_chksum_long(full_name, &my_checksum)){
|
||||
DEMO_ERROR(DEMO_ERROR_DISK_ACCESS);
|
||||
return 0;
|
||||
}
|
||||
if(file_checksum != my_checksum){
|
||||
DEMO_ERROR(DEMO_ERROR_MISSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the file offset of this first frame
|
||||
Demo_cur_offset = cftell(Demo_file);
|
||||
|
||||
// success
|
||||
return 1;
|
||||
}
|
||||
|
||||
// do a playback frame
|
||||
void demo_do_playback_frame()
|
||||
{
|
||||
// seek to the best location in the demo file
|
||||
switch(demo_playback_seek()){
|
||||
// error
|
||||
case 0:
|
||||
return;
|
||||
|
||||
// continue
|
||||
case 1:
|
||||
break;
|
||||
|
||||
// found the trailer - this demo is done
|
||||
case 2:
|
||||
demo_close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// seek through the demo file to the proper location
|
||||
// return 0 on error, 1 on success/continue, 2 if the demo is done
|
||||
int demo_playback_seek()
|
||||
{
|
||||
float this_time = 0.0f;
|
||||
int frame_size;
|
||||
int this_offset;
|
||||
int ret = 0;
|
||||
|
||||
// scan until we find something useful
|
||||
while(1){
|
||||
// record the beginning of this chunk
|
||||
this_offset = cftell(Demo_file);
|
||||
|
||||
// read in the data for the next frame
|
||||
DEMO_DATA_FRAME();
|
||||
frame_size = Demo_buf_pos;
|
||||
Demo_buf_pos = 0;
|
||||
|
||||
// check the time
|
||||
DEMO_FLOAT(this_time);
|
||||
|
||||
// ahead of us
|
||||
if(this_time > f2fl(Missiontime)){
|
||||
// success
|
||||
ret = 1;
|
||||
|
||||
// seek back to the beginning of this chunk
|
||||
Demo_cur_offset = this_offset;
|
||||
|
||||
// bust out
|
||||
break;
|
||||
}
|
||||
// we should scan through this chunk
|
||||
else {
|
||||
// returns true if it finds the demo trailer
|
||||
if(demo_playback_seek_sub(frame_size)){
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// seek back to the new frame
|
||||
cfseek(Demo_file, Demo_cur_offset, CF_SEEK_SET);
|
||||
|
||||
// return
|
||||
return ret;
|
||||
}
|
||||
|
||||
// scan through a read in frame of data and apply everything necessary. returns true if the trailer (end of demo) was found
|
||||
int demo_playback_seek_sub(int frame_size)
|
||||
{
|
||||
ubyte event = 0;
|
||||
int idx;
|
||||
|
||||
// apply everything
|
||||
while(Demo_buf_pos < frame_size){
|
||||
// next event
|
||||
DEMO_UBYTE(event);
|
||||
|
||||
// process it
|
||||
switch(event){
|
||||
// oops, trailer. we're done
|
||||
case DE_TRAILER:
|
||||
return 1;
|
||||
|
||||
// object dump
|
||||
case DE_DUMP: {
|
||||
ushort obj_count = 0;
|
||||
int obj_sig = 0;
|
||||
ubyte team = 0;
|
||||
vec3d obj_pos = vmd_zero_vector;
|
||||
matrix obj_orient = vmd_identity_matrix;
|
||||
float obj_fthrust = 0;
|
||||
int ship_index = 0;
|
||||
int ship_flags = 0;
|
||||
|
||||
// get the object count
|
||||
DEMO_USHORT(obj_count);
|
||||
|
||||
// read in all the objects
|
||||
for(idx=0; idx<obj_count; idx++){
|
||||
DEMO_INT(obj_sig);
|
||||
DEMO_VECTOR(obj_pos);
|
||||
DEMO_MATRIX(obj_orient);
|
||||
DEMO_FLOAT(obj_fthrust);
|
||||
DEMO_UBYTE(team);
|
||||
DEMO_INT(ship_flags);
|
||||
|
||||
// find our ship object
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
// Assert(ship_index >= 0);
|
||||
if(ship_index >= 0){
|
||||
Objects[Ships[ship_index].objnum].pos = obj_pos;
|
||||
Objects[Ships[ship_index].objnum].orient = obj_orient;
|
||||
Objects[Ships[ship_index].objnum].phys_info.forward_thrust = obj_fthrust;
|
||||
Ships[ship_index].team = team;
|
||||
Ships[ship_index].flags = ship_flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// primary fired
|
||||
case DE_PRIMARY: {
|
||||
int obj_sig = 0 ;
|
||||
ubyte fire_info = 0;
|
||||
int ship_index = -1;
|
||||
|
||||
// get the data and ship
|
||||
DEMO_INT(obj_sig);
|
||||
DEMO_UBYTE(fire_info);
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
if(ship_index >= 0){
|
||||
Ships[ship_index].weapons.current_primary_bank = (int)(fire_info & ~(1<<7));
|
||||
if(fire_info & (1<<7)){
|
||||
Ships[ship_index].flags |= SF_PRIMARY_LINKED;
|
||||
} else {
|
||||
Ships[ship_index].flags &= ~(SF_PRIMARY_LINKED);
|
||||
}
|
||||
|
||||
// fire
|
||||
ship_fire_primary(&Objects[Ships[ship_index].objnum], 0, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// unique message
|
||||
case DE_UNIQUE_MESSAGE: {
|
||||
char id[255] = "";
|
||||
char who_from[255] = "";
|
||||
int m_source = 0;
|
||||
int priority = 0;
|
||||
|
||||
// read the stuff in
|
||||
DEMO_STRING(id);
|
||||
DEMO_STRING(who_from);
|
||||
DEMO_INT(m_source);
|
||||
DEMO_INT(priority);
|
||||
|
||||
// send the message
|
||||
message_send_unique_to_player(id, who_from, m_source, priority, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
// builtin message
|
||||
case DE_BUILTIN_MESSAGE:{
|
||||
int type = 0;
|
||||
int sig = 0;
|
||||
int ship_index = 0;
|
||||
int priority = 0;
|
||||
int timing = 0;
|
||||
|
||||
// get data and ship
|
||||
DEMO_INT(type);
|
||||
DEMO_INT(sig);
|
||||
DEMO_INT(priority);
|
||||
DEMO_INT(timing);
|
||||
if(sig == -1){
|
||||
// message_send_builtin_to_player(type, NULL, priority, timing, 0, 0);
|
||||
} else {
|
||||
ship_index = ship_get_by_signature(sig);
|
||||
if(ship_index >= 0){
|
||||
// message_send_builtin_to_player(type, &Ships[ship_index], priority, timing, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// obj create
|
||||
case DE_OBJ_CREATE:{
|
||||
char pobj_name[255] = "";
|
||||
int obj_sig = 0;
|
||||
int objnum = 0;
|
||||
p_object *objp = NULL;
|
||||
|
||||
// try and create the ship
|
||||
DEMO_STRING(pobj_name);
|
||||
DEMO_INT(obj_sig);
|
||||
|
||||
objp = mission_parse_get_arrival_ship( pobj_name );
|
||||
if(objp != NULL){
|
||||
objnum = parse_create_object(objp);
|
||||
if(objnum >= 0){
|
||||
Objects[objnum].signature = obj_sig;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// warpin effect
|
||||
case DE_OBJ_WARPIN:{
|
||||
int obj_sig = 0;
|
||||
int ship_flags = 0;
|
||||
int ship_index = 0;
|
||||
|
||||
// get the data and ship
|
||||
DEMO_INT(obj_sig);
|
||||
DEMO_INT(ship_flags);
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
if(ship_index >= 0){
|
||||
Ships[ship_index].flags = ship_flags;
|
||||
shipfx_warpin_start(&Objects[Ships[ship_index].objnum]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// warpout effect
|
||||
case DE_OBJ_WARPOUT:{
|
||||
int obj_sig = 0;
|
||||
int ship_flags = 0;
|
||||
int ship_index = 0;
|
||||
|
||||
// get the data and ship
|
||||
DEMO_INT(obj_sig);
|
||||
DEMO_INT(ship_flags);
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
if(ship_index >= 0){
|
||||
Ships[ship_index].flags = ship_flags;
|
||||
shipfx_warpout_start(&Objects[Ships[ship_index].objnum]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// departed
|
||||
case DE_OBJ_DEPARTED:{
|
||||
int obj_sig = 0;
|
||||
int ship_flags = 0;
|
||||
int ship_index = 0;
|
||||
|
||||
// get the data and ship
|
||||
DEMO_INT(obj_sig);
|
||||
DEMO_INT(ship_flags);
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
if(ship_index >= 0){
|
||||
Ships[ship_index].flags = ship_flags;
|
||||
ship_actually_depart(ship_index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// ship kill
|
||||
case DE_SHIP_KILL:{
|
||||
int obj_sig = 0;
|
||||
int ship_index = 0;
|
||||
|
||||
// get the data and ship
|
||||
DEMO_INT(obj_sig);
|
||||
ship_index = ship_get_by_signature(obj_sig);
|
||||
if(ship_index >= 0){
|
||||
Objects[Ships[ship_index].objnum].hull_strength = 0.0f;
|
||||
ship_generic_kill_stuff(&Objects[Ships[ship_index].objnum], 1.0f);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 _FS2_DEMO_SYSTEM_HEADER_FILE
|
||||
#define _FS2_DEMO_SYSTEM_HEADER_FILE
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO DEFINES/VARS
|
||||
//
|
||||
|
||||
// compile in the demo system
|
||||
#define DEMO_SYSTEM
|
||||
|
||||
struct object;
|
||||
struct ship;
|
||||
|
||||
// an error reading or writing the demo file
|
||||
#define DEMO_ERROR_NONE 0 // no error
|
||||
#define DEMO_ERROR_GENERAL 1 // general problem
|
||||
#define DEMO_ERROR_FRAMESIZE 2 // frame size was too big (> 32k)
|
||||
#define DEMO_ERROR_DISK_SPACE 3 // out of disk space
|
||||
#define DEMO_ERROR_DISK_ACCESS 4 // problem accessing disk
|
||||
#define DEMO_ERROR_VERSION 5 // bad version #
|
||||
#define DEMO_ERROR_MISSION 6 // different mission file checksums
|
||||
extern int Demo_error;
|
||||
|
||||
extern int Demo_make;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// DEMO FUNCTIONS
|
||||
//
|
||||
|
||||
// do frame for the demo - start for the frame
|
||||
int demo_do_frame_start();
|
||||
|
||||
// do frame for the demo - end for the frame
|
||||
int demo_do_frame_end();
|
||||
|
||||
// initialize a demo for recording
|
||||
// NOTE : call this after loading the mission and going through the briefing, but _before_ physically moving into the mission
|
||||
int demo_start_record(char *file);
|
||||
|
||||
// initialize a demo for playback - calling this will load up the demo file and move the player into the playback state
|
||||
int demo_start_playback(char *file);
|
||||
|
||||
// finish the demo, whether recording or playing back
|
||||
void demo_close();
|
||||
|
||||
// if we should run the simulation for this object, or let the demo system handle it
|
||||
int demo_should_sim(object *objp);
|
||||
|
||||
|
||||
// functions for posting critical events to the demo system ------------------------------------------------------------
|
||||
|
||||
// post an object dump event (only used internally)
|
||||
void demo_POST_object_dump();
|
||||
|
||||
// post a primary fired event
|
||||
void demo_POST_primary_fired(object *objp, int banks, int linked);
|
||||
|
||||
// post a unique message
|
||||
void demo_POST_unique_message(char *id, char *who_from, int m_source, int priority);
|
||||
|
||||
// post a builtin message
|
||||
void demo_POST_builtin_message(int type, ship *shipp, int priority, int timing);
|
||||
|
||||
// post an object create message
|
||||
void demo_POST_obj_create(char *pobj_name, int signature);
|
||||
|
||||
// post a warpin event
|
||||
void demo_POST_warpin(int signature, int ship_flags);
|
||||
|
||||
// post a warpout event
|
||||
void demo_POST_warpout(int signature, int ship_flags);
|
||||
|
||||
// post a departed event
|
||||
void demo_POST_departed(int signature, int ship_flags);
|
||||
|
||||
// post a ship kill event
|
||||
void demo_POST_ship_kill(object *objp);
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
+277
-260
@@ -9,17 +9,17 @@
|
||||
|
||||
|
||||
|
||||
#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 <stdlib.h>
|
||||
|
||||
@@ -47,6 +47,7 @@ fireball_info Fireball_info[MAX_FIREBALL_TYPES];
|
||||
int fireball_used[MAX_FIREBALL_TYPES];
|
||||
|
||||
int Num_fireballs = 0;
|
||||
|
||||
int Num_fireball_types = 0;
|
||||
|
||||
int fireballs_inited = 0;
|
||||
@@ -56,9 +57,7 @@ int Warp_ball_bitmap = -1;
|
||||
|
||||
#define FB_INDEX(fb) (fb-Fireballs)
|
||||
|
||||
/**
|
||||
* Play warp in sound for warp effect
|
||||
*/
|
||||
// play warp in sound for warp effect
|
||||
void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
|
||||
{
|
||||
int sound_index;
|
||||
@@ -75,7 +74,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;
|
||||
@@ -88,9 +87,7 @@ void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
|
||||
snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
|
||||
}
|
||||
|
||||
/**
|
||||
* Play warp out sound for warp effect
|
||||
*/
|
||||
// play warp out sound for warp effect
|
||||
void fireball_play_warphole_close_sound(fireball *fb)
|
||||
{
|
||||
int sound_index;
|
||||
@@ -106,15 +103,14 @@ void fireball_play_warphole_close_sound(fireball *fb)
|
||||
} else if ( fb->flags & FBF_WARP_CAPITAL_SIZE ) {
|
||||
sound_index = SND_CAPITAL_WARP_OUT;
|
||||
} else {
|
||||
// AL 27-3-98: Decided that warphole closing is only required for capital ship sized warp effects.
|
||||
return;
|
||||
}
|
||||
|
||||
snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default colors for each explosion type (original values from object.cpp)
|
||||
*/
|
||||
// set default colors for each explosion type (original values from object.cpp)
|
||||
static void fireball_set_default_color(int idx)
|
||||
{
|
||||
Assert( (idx >= 0) && (idx < MAX_FIREBALL_TYPES) );
|
||||
@@ -151,106 +147,99 @@ static void fireball_set_default_color(int idx)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse fireball tbl
|
||||
*
|
||||
* 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)
|
||||
// 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(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()
|
||||
{
|
||||
int i = 0, j;
|
||||
SCP_vector<lod_checker>::iterator lod;
|
||||
int i, j;
|
||||
|
||||
memset( &Fireball_info, 0, sizeof(fireball_info) * MAX_FIREBALL_TYPES );
|
||||
|
||||
@@ -262,10 +251,10 @@ void fireball_parse_tbl()
|
||||
|
||||
// we've got our list so pass it off for final checking and loading.
|
||||
// we assume that entries in fireball.tbl are in the correct order
|
||||
for (lod = LOD_checker.begin(); lod != LOD_checker.end(); ++lod) {
|
||||
if ( (i < MAX_FIREBALL_TYPES) && (lod->override < 0) ) {
|
||||
strcpy_s( Fireball_info[i].lod[0].filename, lod->filename );
|
||||
Fireball_info[i].lod_count = lod->num_lods;
|
||||
for (i = 0; i < (int)LOD_checker.size(); i++) {
|
||||
if ( (i < MAX_FIREBALL_TYPES) && (LOD_checker[i].override < 0) ) {
|
||||
strcpy_s( Fireball_info[i].lod[0].filename, LOD_checker[i].filename );
|
||||
Fireball_info[i].lod_count = LOD_checker[i].num_lods;
|
||||
Num_fireball_types++;
|
||||
|
||||
if (LOD_color[i].alpha == 255) {
|
||||
@@ -276,24 +265,22 @@ void fireball_parse_tbl()
|
||||
fireball_set_default_color(i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// having to do this twice is less than optimal, but less error prone too.
|
||||
// this handles (and should only have to handle) TBM related entries
|
||||
i = 0;
|
||||
for (lod = LOD_checker.begin(); lod != LOD_checker.end(); ++lod) {
|
||||
for (i = 0; i < (int)LOD_checker.size(); i++) {
|
||||
// try entry replacement
|
||||
if ( (lod->override >= 0) && (lod->override < Num_fireball_types) ) {
|
||||
strcpy_s( Fireball_info[lod->override].lod[0].filename, lod->filename );
|
||||
Fireball_info[lod->override].lod_count = lod->num_lods;
|
||||
if ( (LOD_checker[i].override >= 0) && (LOD_checker[i].override < Num_fireball_types) ) {
|
||||
strcpy_s( Fireball_info[LOD_checker[i].override].lod[0].filename, LOD_checker[i].filename );
|
||||
Fireball_info[LOD_checker[i].override].lod_count = LOD_checker[i].num_lods;
|
||||
|
||||
if (LOD_color[i].alpha == 255) {
|
||||
Fireball_info[lod->override].exp_color[0] = (LOD_color[i].red / 255.0f);
|
||||
Fireball_info[lod->override].exp_color[1] = (LOD_color[i].green / 255.0f);
|
||||
Fireball_info[lod->override].exp_color[2] = (LOD_color[i].blue / 255.0f);
|
||||
Fireball_info[LOD_checker[i].override].exp_color[0] = (LOD_color[i].red / 255.0f);
|
||||
Fireball_info[LOD_checker[i].override].exp_color[1] = (LOD_color[i].green / 255.0f);
|
||||
Fireball_info[LOD_checker[i].override].exp_color[2] = (LOD_color[i].blue / 255.0f);
|
||||
} else {
|
||||
fireball_set_default_color(lod->override);
|
||||
fireball_set_default_color(LOD_checker[i].override);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,7 +310,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);
|
||||
}
|
||||
@@ -336,6 +323,15 @@ void fireball_load_data()
|
||||
if ( Warp_ball_bitmap == -1 ) {
|
||||
Warp_ball_bitmap = bm_load( NOX("warpball01") );
|
||||
}
|
||||
|
||||
// polymodel Warp_pm;
|
||||
|
||||
}
|
||||
|
||||
void fireball_preload()
|
||||
{
|
||||
// Do nothing. Called before level init, this used to page in warp effect.
|
||||
// Not needed with new BmpMan system.
|
||||
}
|
||||
|
||||
// This will get called at the start of each level.
|
||||
@@ -374,10 +370,91 @@ void fireball_init()
|
||||
|
||||
MONITOR( NumFireballsRend )
|
||||
|
||||
/**
|
||||
* Delete a fireball.
|
||||
* Called by object_delete() code... do not call directly.
|
||||
*/
|
||||
void fireball_render(object * obj)
|
||||
{
|
||||
// if(!Cmdline_nohtl)gr_set_lighting(false,false);
|
||||
|
||||
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;
|
||||
|
||||
// gr_set_color( 0, 100, 0 );
|
||||
// g3_draw_sphere_ez( &obj->pos, obj->radius );
|
||||
// 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:
|
||||
gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
|
||||
g3_draw_bitmap(&p, fb->orient, obj->radius, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT );
|
||||
break;
|
||||
|
||||
case FIREBALL_LARGE_EXPLOSION:
|
||||
// Make the big explosions rotate with the viewer.
|
||||
gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
|
||||
g3_draw_rotated_bitmap(&p, (i2fl(fb->orient)*PI)/180.0f, obj->radius, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
|
||||
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;
|
||||
//rad = t*obj->radius/WARPHOLE_GROW_TIME;
|
||||
//mprintf(( "T=%.2f, Rad = %.2f\n", t, rad ));
|
||||
} 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;
|
||||
//rad = (fb->total_time - t )*obj->radius/WARPHOLE_GROW_TIME;
|
||||
}
|
||||
//rad = obj->radius;
|
||||
// obj->alt_rad = rad;
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// fireball_delete()
|
||||
//
|
||||
// Delete a fireball. Called by object_delete() code... do not call
|
||||
// directly.
|
||||
//
|
||||
void fireball_delete( object * obj )
|
||||
{
|
||||
int num;
|
||||
@@ -393,9 +470,11 @@ void fireball_delete( object * obj )
|
||||
Assert( Num_fireballs >= 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all active fireballs, by calling obj_delete directly.
|
||||
*/
|
||||
// -----------------------------------------------------------------
|
||||
// fireball_delete_all()
|
||||
//
|
||||
// Delete all active fireballs, by calling obj_delete directly.
|
||||
//
|
||||
void fireball_delete_all()
|
||||
{
|
||||
fireball *fb;
|
||||
@@ -430,7 +509,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 +525,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;
|
||||
}
|
||||
}
|
||||
@@ -471,12 +564,12 @@ int fireball_is_perishable(object * obj)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* There are too many fireballs, so delete the oldest small one
|
||||
* to free up a slot.
|
||||
*
|
||||
* @return The fireball slot freed.
|
||||
*/
|
||||
// -----------------------------------------------------------------
|
||||
// fireball_free_one()
|
||||
//
|
||||
// There are too many fireballs, so delete the oldest small one
|
||||
// to free up a slot. Returns the fireball slot freed.
|
||||
//
|
||||
int fireball_free_one()
|
||||
{
|
||||
fireball *fb;
|
||||
@@ -507,6 +600,12 @@ int fireball_free_one()
|
||||
return oldest_slotnum;
|
||||
}
|
||||
|
||||
// broke fireball_move into fireball_process_pre and fireball_process_post as was done
|
||||
// with all *_move functions on 8/13 by Mike K. and Mark A.
|
||||
void fireball_process_pre( object *objp, float frame_time)
|
||||
{
|
||||
}
|
||||
|
||||
int fireball_is_warp(object * obj)
|
||||
{
|
||||
int num, objnum;
|
||||
@@ -572,9 +671,7 @@ void fireball_process_post(object * obj, float frame_time)
|
||||
fireball_set_framenum(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns life left of a fireball in seconds
|
||||
*/
|
||||
// Returns life left of a fireball in seconds
|
||||
float fireball_lifeleft( object *obj )
|
||||
{
|
||||
int num, objnum;
|
||||
@@ -589,9 +686,7 @@ float fireball_lifeleft( object *obj )
|
||||
return fb->total_time - fb->time_elapsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns life left of a fireball in percent
|
||||
*/
|
||||
// Returns life left of a fireball in percent
|
||||
float fireball_lifeleft_percent( object *obj )
|
||||
{
|
||||
int num, objnum;
|
||||
@@ -603,14 +698,14 @@ float fireball_lifeleft_percent( object *obj )
|
||||
|
||||
fb = &Fireballs[num];
|
||||
|
||||
// Assert((fb->total_time - fb->time_elapsed) / fb->total_time >=0);
|
||||
|
||||
float p = (fb->total_time - fb->time_elapsed) / fb->total_time;
|
||||
if (p < 0)p=0.0f;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine LOD to use
|
||||
*/
|
||||
// determine LOD to use
|
||||
int fireball_get_lod(vec3d *pos, fireball_info *fd, float size)
|
||||
{
|
||||
vertex v;
|
||||
@@ -691,9 +786,7 @@ int fireball_get_lod(vec3d *pos, fireball_info *fd, float size)
|
||||
return MIN(ret_lod, fd->lod_count - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fireball, return object index.
|
||||
*/
|
||||
// Create a fireball, return object index.
|
||||
int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent_obj, float size, int reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, int warp_open_sound, int warp_close_sound)
|
||||
{
|
||||
int n, objnum, fb_lod;
|
||||
@@ -718,11 +811,22 @@ int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent
|
||||
}
|
||||
|
||||
if ( (Num_fireballs >= MAX_FIREBALLS) || (Num_objects >= MAX_OBJECTS) ) {
|
||||
// who cares if we don't create a spark.
|
||||
// JAS - Should this code be in? Is it better to remove an old spark
|
||||
// and start a new one, or just not start the new one?
|
||||
//if ( fd->type == FIREBALL_TYPE_SMALL ) {
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//mprintf(( "Out of fireball slots, trying to free one up!\n" ));
|
||||
// out of slots, so free one up.
|
||||
n = fireball_free_one();
|
||||
if ( n < 0 ) {
|
||||
if ( n < 0 ) {
|
||||
// If there's still no free slots, then exit
|
||||
//mprintf(( "ERROR: Couldn't free one up!!\n" ));
|
||||
return -1;
|
||||
} else {
|
||||
//mprintf(( "Freed one up just fine!!\n" ));
|
||||
}
|
||||
} else {
|
||||
for ( n = 0; n < MAX_FIREBALLS; n++ ) {
|
||||
@@ -746,6 +850,11 @@ int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent
|
||||
|
||||
// if this is a warpout fireball, never go higher than LOD 1
|
||||
if(fireball_type == FIREBALL_WARP){
|
||||
/*
|
||||
if(fb_lod > 1){
|
||||
fb_lod = 1;
|
||||
}
|
||||
*/
|
||||
fb_lod = MAX_WARP_LOD;
|
||||
}
|
||||
fl = &fd->lod[fb_lod];
|
||||
@@ -840,9 +949,11 @@ int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent
|
||||
return objnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at game shutdown to clean up the fireball system
|
||||
*/
|
||||
// -----------------------------------------------------------------
|
||||
// fireball_close()
|
||||
//
|
||||
// Called at game shutdown to clean up the fireball system
|
||||
//
|
||||
void fireball_close()
|
||||
{
|
||||
if ( !fireballs_inited )
|
||||
@@ -851,6 +962,20 @@ void fireball_close()
|
||||
fireball_delete_all();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// fireball_level_close()
|
||||
//
|
||||
// Called when a mission ends... frees up any animations that might
|
||||
// be partially played
|
||||
//
|
||||
void fireball_level_close()
|
||||
{
|
||||
if ( !fireballs_inited )
|
||||
return;
|
||||
|
||||
fireball_delete_all();
|
||||
}
|
||||
|
||||
void fireballs_page_in()
|
||||
{
|
||||
int i, idx;
|
||||
@@ -919,111 +1044,3 @@ int fireball_ship_explosion_type(ship_info *sip)
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int fireball_asteroid_explosion_type(asteroid_info *aip)
|
||||
{
|
||||
Assert( aip != NULL );
|
||||
|
||||
if (aip->explosion_bitmap_anims.empty())
|
||||
return -1;
|
||||
|
||||
int index = -1;
|
||||
int roid_fireballs = (int)aip->explosion_bitmap_anims.size();
|
||||
|
||||
if (roid_fireballs > 0) {
|
||||
index = aip->explosion_bitmap_anims[rand()%roid_fireballs];
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
float fireball_wormhole_intensity( object *obj )
|
||||
{
|
||||
int num, objnum;
|
||||
fireball *fb;
|
||||
|
||||
num = obj->instance;
|
||||
objnum = OBJ_INDEX(obj);
|
||||
Assertion( Fireballs[num].objnum == objnum, "Basic sanity check. Fireballs[num].objnum (%d) should == objnum (%d)", Fireballs[num].objnum, objnum );
|
||||
|
||||
fb = &Fireballs[num];
|
||||
|
||||
float t = fb->time_elapsed;
|
||||
float rad;
|
||||
|
||||
if ( t < WARPHOLE_GROW_TIME ) {
|
||||
rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f);
|
||||
} else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
|
||||
rad = 1;
|
||||
} else {
|
||||
rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f);
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
+24
-31
@@ -13,11 +13,9 @@
|
||||
#define _FIREBALLS_H
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "model/modelrender.h"
|
||||
|
||||
class object;
|
||||
class ship_info;
|
||||
class asteroid_info;
|
||||
struct object;
|
||||
struct ship_info;
|
||||
|
||||
// values correspond to the fireball render types
|
||||
#define FIREBALL_MEDIUM_EXPLOSION 0
|
||||
@@ -25,15 +23,15 @@ class asteroid_info;
|
||||
#define FIREBALL_WARP_EFFECT 2
|
||||
|
||||
// these values correspond to the fireball.tbl default entries
|
||||
#define FIREBALL_EXPLOSION_MEDIUM 0 // Used for the 4 little explosions before a ship explodes
|
||||
#define FIREBALL_WARP 1 // Used for the warp in / warp out effect
|
||||
#define FIREBALL_KNOSSOS 2 // Used for the KNOSSOS warp in / warp out effect
|
||||
#define FIREBALL_ASTEROID 3
|
||||
#define FIREBALL_EXPLOSION_LARGE1 4 // Used for the big explosion when a ship breaks into pieces
|
||||
#define FIREBALL_EXPLOSION_LARGE2 5 // Used for the big explosion when a ship breaks into pieces
|
||||
#define FIREBALL_EXPLOSION_MEDIUM 0 // Used for the 4 little explosions before a ship explodes
|
||||
#define FIREBALL_WARP 1 // Used for the warp in / warp out effect
|
||||
#define FIREBALL_KNOSSOS 2 // Used for the KNOSSOS warp in / warp out effect
|
||||
#define FIREBALL_ASTEROID 3
|
||||
#define FIREBALL_EXPLOSION_LARGE1 4 // Used for the big explosion when a ship breaks into pieces
|
||||
#define FIREBALL_EXPLOSION_LARGE2 5 // Used for the big explosion when a ship breaks into pieces
|
||||
|
||||
#define MAX_FIREBALL_TYPES 32 // The maximum number of fireballs that can be defined
|
||||
#define NUM_DEFAULT_FIREBALLS 6
|
||||
#define MAX_FIREBALL_TYPES 32 // The maximum number of fireballs that can be defined
|
||||
#define NUM_DEFAULT_FIREBALLS 6
|
||||
|
||||
#define FIREBALL_NUM_LARGE_EXPLOSIONS 2
|
||||
|
||||
@@ -43,12 +41,12 @@ extern int Num_fireball_types;
|
||||
// all this moved here by Goober5000 because it makes more sense in the H file
|
||||
typedef struct fireball_lod {
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
int bitmap_id;
|
||||
int num_frames;
|
||||
int fps;
|
||||
int bitmap_id;
|
||||
int num_frames;
|
||||
int fps;
|
||||
} fireball_lod;
|
||||
|
||||
typedef struct fireball_info {
|
||||
typedef struct fireball_info {
|
||||
int lod_count;
|
||||
float exp_color[3];
|
||||
fireball_lod lod[4];
|
||||
@@ -61,24 +59,25 @@ typedef struct fireball_info {
|
||||
#define FBF_WARP_3D (1<<3) // Goober5000
|
||||
#define FBF_WARP_VIA_SEXP (1<<4) // Goober5000
|
||||
|
||||
typedef struct fireball {
|
||||
typedef struct fireball {
|
||||
int objnum; // If -1 this object is unused
|
||||
int fireball_info_index; // Index into Fireball_info array
|
||||
int fireball_render_type;
|
||||
int current_bitmap;
|
||||
int orient; // For fireballs, which orientation. For warps, 0 is warpin, 1 is warpout
|
||||
int flags; // see #define FBF_*
|
||||
char lod; // current LOD
|
||||
float time_elapsed; // in seconds
|
||||
float total_time; // total lifetime of animation in seconds
|
||||
int warp_open_sound_index; // for warp-effect - Goober5000
|
||||
int warp_close_sound_index; // for warp-effect - Goober5000
|
||||
char lod; // current LOD
|
||||
float time_elapsed; // in seconds
|
||||
float total_time; // total lifetime of animation in seconds
|
||||
int warp_open_sound_index; // for warp-effect - Goober5000
|
||||
int warp_close_sound_index; // for warp-effect - Goober5000
|
||||
} 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_pre(object * obj, float frame_time);
|
||||
void fireball_process_post(object * obj, float frame_time);
|
||||
|
||||
// reversed is for warp_in/out effects
|
||||
@@ -87,6 +86,8 @@ void fireball_process_post(object * obj, float frame_time);
|
||||
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, int reversed=0, vec3d *velocity=NULL, float warp_lifetime=0.0f, int ship_class=-1, matrix *orient=NULL, int low_res=0, int extra_flags=0, int warp_open_sound=-1, int warp_close_sound=-1);
|
||||
void fireball_render_plane(int plane);
|
||||
void fireball_close();
|
||||
void fireball_level_close();
|
||||
void fireball_preload(); // page in warpout effect data
|
||||
|
||||
// Returns 1 if you can remove this fireball
|
||||
int fireball_is_perishable(object * obj);
|
||||
@@ -106,17 +107,9 @@ void fireball_get_color(int idx, float *red, float *green, float *blue);
|
||||
// returns the index of the fireball bitmap for this ship. -1 if there is none.
|
||||
int fireball_ship_explosion_type(ship_info *sip);
|
||||
|
||||
// returns the index of the fireball bitmap for this asteroid. -1 if there is none.
|
||||
int fireball_asteroid_explosion_type(asteroid_info *aip);
|
||||
|
||||
// returns the intensity of a wormhole
|
||||
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
|
||||
|
||||
+39
-189
@@ -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;
|
||||
@@ -30,8 +32,8 @@ void draw_face( 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 ) {
|
||||
vm_vec_perp(&norm,(vec3d *)&v1->x, (vec3d *)&v2->x, (vec3d *)&v3->x);
|
||||
if ( vm_vec_dot(&norm, (vec3d *)&v1->x ) >= 0.0 ) {
|
||||
vertlist[0] = v3;
|
||||
vertlist[1] = v2;
|
||||
vertlist[2] = v1;
|
||||
@@ -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;
|
||||
@@ -110,9 +92,13 @@ 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;
|
||||
verts[4].u = 0.5f; verts[4].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;
|
||||
|
||||
@@ -158,26 +141,25 @@ void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_n
|
||||
// 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[0].u = 0.01f; verts[0].v = 0.01f;
|
||||
verts[1].u = 0.99f; verts[1].v = 0.01f;
|
||||
verts[2].u = 0.99f; verts[2].v = 0.99f;
|
||||
verts[3].u = 0.01f; verts[3].v = 0.99f;
|
||||
verts[4].u = 0.5f; verts[4].v = 0.5f;
|
||||
|
||||
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] );
|
||||
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 +187,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+406
-406
@@ -1,406 +1,406 @@
|
||||
/*
|
||||
* Created by Hassan "Karajorma" Kazmi for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
// AltShipClassDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "fred.h"
|
||||
#include "AltShipClassDlg.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg dialog
|
||||
|
||||
|
||||
AltShipClassDlg::AltShipClassDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(AltShipClassDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(AltShipClassDlg)
|
||||
m_selected_variable = -1;
|
||||
m_selected_class = -1;
|
||||
//}}AFX_DATA_INIT
|
||||
|
||||
multi_edit = false;
|
||||
player_ships_only = true;
|
||||
num_string_variables = 0;
|
||||
|
||||
memset(string_variable_indices, -1, sizeof (int)*MAX_SEXP_VARIABLES);
|
||||
memset(ship_class_indices, -1, sizeof (int)*MAX_SHIP_CLASSES);
|
||||
}
|
||||
|
||||
|
||||
void AltShipClassDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(AltShipClassDlg)
|
||||
DDX_Control(pDX, IDC_DEFAULT_TO_CLASS, m_default_to_class);
|
||||
DDX_Control(pDX, IDC_ALT_CLASS_LIST, m_alt_class_list);
|
||||
DDX_Control(pDX, IDC_SET_FROM_SHIP_CLASS, m_set_from_ship_class);
|
||||
DDX_Control(pDX, IDC_SET_FROM_VARIABLES, m_set_from_variables);
|
||||
DDX_CBIndex(pDX, IDC_SET_FROM_VARIABLES, m_selected_variable);
|
||||
DDX_CBIndex(pDX, IDC_SET_FROM_SHIP_CLASS, m_selected_class);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(AltShipClassDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(AltShipClassDlg)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_ADD, OnAltClassAdd)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_INSERT, OnAltClassInsert)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_DELETE, OnAltClassDelete)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_UP, OnMoveUp)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_DOWN, OnMoveDown)
|
||||
ON_CBN_SELENDOK(IDC_SET_FROM_SHIP_CLASS, OnSelendokSetFromShipClass)
|
||||
ON_CBN_SELENDOK(IDC_SET_FROM_VARIABLES, OnSelendokSetFromVariables)
|
||||
ON_LBN_SELCHANGE(IDC_ALT_CLASS_LIST, OnSelchangeAltClassList)
|
||||
ON_BN_CLICKED(IDC_DEFAULT_TO_CLASS, OnDefaultToClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg message handlers
|
||||
|
||||
|
||||
BOOL AltShipClassDlg::OnInitDialog()
|
||||
{
|
||||
int i, count;
|
||||
char buff[TOKEN_LENGTH + TOKEN_LENGTH + 2]; // VariableName[VariableValue]
|
||||
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// have we got multiple selected ships?
|
||||
num_selected_ships = 0;
|
||||
object *objp;
|
||||
|
||||
objp = GET_FIRST(&obj_used_list);
|
||||
while (objp != END_OF_LIST(&obj_used_list)) {
|
||||
if ((objp->type == OBJ_START) || (objp->type == OBJ_SHIP)) {
|
||||
if (objp->flags & OF_MARKED) {
|
||||
m_selected_ships[num_selected_ships++] = objp->instance;
|
||||
}
|
||||
}
|
||||
objp = GET_NEXT(objp);
|
||||
}
|
||||
|
||||
Assert (num_selected_ships > 0);
|
||||
Assert (Objects[cur_object_index].flags & OF_MARKED);
|
||||
|
||||
if (num_selected_ships > 1)
|
||||
{
|
||||
multi_edit = true;
|
||||
}
|
||||
|
||||
// Fill the variable combo box
|
||||
m_set_from_variables.ResetContent();
|
||||
m_set_from_variables.AddString("Set From Ship Class");
|
||||
for (i=0; i < MAX_SEXP_VARIABLES; i++)
|
||||
{
|
||||
if (Sexp_variables[i].type & SEXP_VARIABLE_STRING)
|
||||
{
|
||||
sprintf(buff, "%s[%s]", Sexp_variables[i].variable_name, Sexp_variables[i].text);
|
||||
m_set_from_variables.AddString(buff);
|
||||
string_variable_indices[num_string_variables++] = i;
|
||||
}
|
||||
}
|
||||
m_set_from_variables.SetCurSel(0);
|
||||
if (!num_string_variables) {
|
||||
m_set_from_variables.EnableWindow(FALSE);
|
||||
}
|
||||
|
||||
// Fill the ship classes combo box
|
||||
m_set_from_ship_class.ResetContent();
|
||||
// Add the default entry if we need one followed by all the ship classes
|
||||
if (num_string_variables) {
|
||||
m_set_from_ship_class.AddString("Set From Variable");
|
||||
}
|
||||
count = 0;
|
||||
for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it)
|
||||
{
|
||||
if (player_ships_only && !(it->flags & SIF_PLAYER_SHIP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ship_class_indices[count++] = std::distance(Ship_info.cbegin(), it);
|
||||
m_set_from_ship_class.AddString(it->name);
|
||||
}
|
||||
m_set_from_ship_class.SetCurSel(num_string_variables?1:0); // Set to the first ship class
|
||||
|
||||
// Set up the actual list of alt classes
|
||||
alt_class_pool.clear();
|
||||
alt_class_pool = Ships[Objects[cur_object_index].instance].s_alt_classes;
|
||||
alt_class_list_rebuild();
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
|
||||
void AltShipClassDlg::alt_class_list_rebuild()
|
||||
{
|
||||
int i, j;
|
||||
char buff[TOKEN_LENGTH + TOKEN_LENGTH + 2]; // VariableName[VariableValue]
|
||||
|
||||
j = m_alt_class_list.GetCount();
|
||||
for ( i=0; i < j ; i++) {
|
||||
m_alt_class_list.DeleteString(0);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)alt_class_pool.size() ; i++) {
|
||||
// Default classes should be at the end of the list
|
||||
if(alt_class_pool[i].default_to_this_class && (i < (int)alt_class_pool.size() - 1) ) {
|
||||
// Int3();
|
||||
// TO DO : we should fix this.
|
||||
}
|
||||
|
||||
if (alt_class_pool[i].variable_index != -1) {
|
||||
Assert (alt_class_pool[i].variable_index > -1 && alt_class_pool[i].variable_index < MAX_SEXP_VARIABLES);
|
||||
Assert (Sexp_variables[alt_class_pool[i].variable_index].type & SEXP_VARIABLE_STRING);
|
||||
|
||||
sprintf(buff, "%s[%s]", Sexp_variables[alt_class_pool[i].variable_index].variable_name, Sexp_variables[alt_class_pool[i].variable_index].text);
|
||||
|
||||
// add it to the list
|
||||
m_alt_class_list.AddString(buff);
|
||||
}
|
||||
else {
|
||||
if (alt_class_pool[i].ship_class >= 0 && alt_class_pool[i].ship_class < MAX_SHIP_CLASSES) {
|
||||
m_alt_class_list.AddString(Ship_info[alt_class_pool[i].ship_class].name);
|
||||
}
|
||||
else {
|
||||
m_alt_class_list.AddString("Invalid Ship Class");
|
||||
Int3();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnCancel()
|
||||
{
|
||||
// TODO: Add extra cleanup here
|
||||
|
||||
CDialog::OnCancel();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnOK()
|
||||
{
|
||||
// TODO: Add extra validation here
|
||||
|
||||
for (int i=0; i < num_selected_ships; i++) {
|
||||
Ships[m_selected_ships[i]].s_alt_classes = alt_class_pool;
|
||||
}
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassAdd()
|
||||
{
|
||||
alt_class new_list_item;
|
||||
|
||||
alt_class_update_entry(new_list_item);
|
||||
|
||||
alt_class_pool.push_back(new_list_item);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassInsert()
|
||||
{
|
||||
int index;
|
||||
alt_class new_list_item;
|
||||
alt_class_update_entry(new_list_item);
|
||||
|
||||
index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// If nothing is selected just add it
|
||||
if ( index == -1) {
|
||||
alt_class_pool.push_back(new_list_item);
|
||||
}
|
||||
// Stick it in front of the current selection
|
||||
else {
|
||||
alt_class_pool.insert(alt_class_pool.begin() + index, new_list_item );
|
||||
}
|
||||
|
||||
alt_class_list_rebuild();
|
||||
|
||||
// If we inserted the user will probably want to edit the selection
|
||||
if (index > -1) {
|
||||
m_alt_class_list.SetCurSel(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the currently selected list entry
|
||||
void AltShipClassDlg::alt_class_update_entry(alt_class &list_item)
|
||||
{
|
||||
int index;
|
||||
|
||||
// Add a string variable to the list
|
||||
if (num_string_variables && m_set_from_variables.GetCurSel() > 0) {
|
||||
index = string_variable_indices[m_set_from_variables.GetCurSel() -1];
|
||||
|
||||
Assert (index >= 0);
|
||||
list_item.variable_index = index;
|
||||
list_item.ship_class = ship_info_lookup(Sexp_variables[index].text);
|
||||
}
|
||||
// Add a ship class to the list
|
||||
else {
|
||||
index = m_set_from_ship_class.GetCurSel();
|
||||
|
||||
// Correct the index if the first entry isn't actually a ship class
|
||||
if (num_string_variables) {
|
||||
Assert (index > 0);
|
||||
index--;
|
||||
}
|
||||
|
||||
list_item.variable_index = -1;
|
||||
list_item.ship_class = ship_class_indices[index];
|
||||
}
|
||||
|
||||
// check the default tickbox
|
||||
list_item.default_to_this_class = m_default_to_class.GetCheck() ? true:false;
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassDelete()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert (index < (int) alt_class_pool.size());
|
||||
alt_class_pool.erase(alt_class_pool.begin()+index);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnMoveUp()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected or already at the top
|
||||
if (index < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap(alt_class_pool[index], alt_class_pool[index-1]);
|
||||
alt_class_list_rebuild();
|
||||
m_alt_class_list.SetCurSel(index-1);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnMoveDown()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
int inext = index + 1;
|
||||
|
||||
// Nothing selected or already at the bottom
|
||||
if (index == -1 || (index >= m_alt_class_list.GetCount() - 1) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap(alt_class_pool[index], alt_class_pool[inext]);
|
||||
alt_class_list_rebuild();
|
||||
m_alt_class_list.SetCurSel(index);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelendokSetFromShipClass()
|
||||
{
|
||||
int current_selection;
|
||||
|
||||
if (m_set_from_ship_class.GetCurSel() == 0 && num_string_variables) {
|
||||
m_set_from_variables.SetCurSel(1);
|
||||
}
|
||||
else {
|
||||
m_set_from_variables.SetCurSel(0);
|
||||
}
|
||||
|
||||
// if a list entry is selected we should update it
|
||||
current_selection = m_alt_class_list.GetCurSel();
|
||||
if (current_selection >= 0) {
|
||||
alt_class_update_entry(alt_class_pool[m_alt_class_list.GetCurSel()]);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelendokSetFromVariables()
|
||||
{
|
||||
int current_selection;
|
||||
|
||||
if (m_set_from_variables.GetCurSel() == 0) {
|
||||
m_set_from_ship_class.SetCurSel(num_string_variables ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
m_set_from_ship_class.SetCurSel(0);
|
||||
}
|
||||
|
||||
// if a list entry is selected we should update it
|
||||
current_selection = m_alt_class_list.GetCurSel();
|
||||
if (current_selection >= 0) {
|
||||
alt_class_update_entry(alt_class_pool[m_alt_class_list.GetCurSel()]);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelchangeAltClassList()
|
||||
{
|
||||
int i;
|
||||
int variable_selection = 0;
|
||||
int ship_selection = 0;
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Selected nothing
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a variable selected
|
||||
if (alt_class_pool[index].variable_index != -1) {
|
||||
for (i=0; i < MAX_SEXP_VARIABLES; i++)
|
||||
{
|
||||
if (string_variable_indices[i] == alt_class_pool[index].variable_index) {
|
||||
variable_selection = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ship selected
|
||||
else {
|
||||
for (i=0; i < MAX_SHIP_CLASSES; i++) {
|
||||
if (ship_class_indices[i] == alt_class_pool[index].ship_class) {
|
||||
ship_selection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have string variables in the mission the first entry on the list won't be a ship
|
||||
if (num_string_variables) {
|
||||
ship_selection++;
|
||||
}
|
||||
}
|
||||
|
||||
m_set_from_variables.SetCurSel(variable_selection);
|
||||
m_set_from_ship_class.SetCurSel(ship_selection);
|
||||
m_default_to_class.SetCheck(alt_class_pool[index].default_to_this_class ? 1:0);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnDefaultToClass()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
alt_class_pool[index].default_to_this_class = m_default_to_class.GetCheck() ? true:false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Created by Hassan "Karajorma" Kazmi for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
// AltShipClassDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "fred.h"
|
||||
#include "AltShipClassDlg.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg dialog
|
||||
|
||||
|
||||
AltShipClassDlg::AltShipClassDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(AltShipClassDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(AltShipClassDlg)
|
||||
m_selected_variable = -1;
|
||||
m_selected_class = -1;
|
||||
//}}AFX_DATA_INIT
|
||||
|
||||
multi_edit = false;
|
||||
player_ships_only = true;
|
||||
num_string_variables = 0;
|
||||
|
||||
memset(string_variable_indices, -1, sizeof (int)*MAX_SEXP_VARIABLES);
|
||||
memset(ship_class_indices, -1, sizeof (int)*MAX_SHIP_CLASSES);
|
||||
}
|
||||
|
||||
|
||||
void AltShipClassDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(AltShipClassDlg)
|
||||
DDX_Control(pDX, IDC_DEFAULT_TO_CLASS, m_default_to_class);
|
||||
DDX_Control(pDX, IDC_ALT_CLASS_LIST, m_alt_class_list);
|
||||
DDX_Control(pDX, IDC_SET_FROM_SHIP_CLASS, m_set_from_ship_class);
|
||||
DDX_Control(pDX, IDC_SET_FROM_VARIABLES, m_set_from_variables);
|
||||
DDX_CBIndex(pDX, IDC_SET_FROM_VARIABLES, m_selected_variable);
|
||||
DDX_CBIndex(pDX, IDC_SET_FROM_SHIP_CLASS, m_selected_class);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(AltShipClassDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(AltShipClassDlg)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_ADD, OnAltClassAdd)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_INSERT, OnAltClassInsert)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_DELETE, OnAltClassDelete)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_UP, OnMoveUp)
|
||||
ON_BN_CLICKED(IDC_ALT_CLASS_DOWN, OnMoveDown)
|
||||
ON_CBN_SELENDOK(IDC_SET_FROM_SHIP_CLASS, OnSelendokSetFromShipClass)
|
||||
ON_CBN_SELENDOK(IDC_SET_FROM_VARIABLES, OnSelendokSetFromVariables)
|
||||
ON_LBN_SELCHANGE(IDC_ALT_CLASS_LIST, OnSelchangeAltClassList)
|
||||
ON_BN_CLICKED(IDC_DEFAULT_TO_CLASS, OnDefaultToClass)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg message handlers
|
||||
|
||||
|
||||
BOOL AltShipClassDlg::OnInitDialog()
|
||||
{
|
||||
int i, count;
|
||||
char buff[TOKEN_LENGTH + TOKEN_LENGTH + 2]; // VariableName[VariableValue]
|
||||
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
// have we got multiple selected ships?
|
||||
num_selected_ships = 0;
|
||||
object *objp;
|
||||
|
||||
objp = GET_FIRST(&obj_used_list);
|
||||
while (objp != END_OF_LIST(&obj_used_list)) {
|
||||
if ((objp->type == OBJ_START) || (objp->type == OBJ_SHIP)) {
|
||||
if (objp->flags & OF_MARKED) {
|
||||
m_selected_ships[num_selected_ships++] = objp->instance;
|
||||
}
|
||||
}
|
||||
objp = GET_NEXT(objp);
|
||||
}
|
||||
|
||||
Assert (num_selected_ships > 0);
|
||||
Assert (Objects[cur_object_index].flags & OF_MARKED);
|
||||
|
||||
if (num_selected_ships > 1)
|
||||
{
|
||||
multi_edit = true;
|
||||
}
|
||||
|
||||
// Fill the variable combo box
|
||||
m_set_from_variables.ResetContent();
|
||||
m_set_from_variables.AddString("Set From Ship Class");
|
||||
for (i=0; i < MAX_SEXP_VARIABLES; i++)
|
||||
{
|
||||
if (Sexp_variables[i].type & SEXP_VARIABLE_STRING)
|
||||
{
|
||||
sprintf(buff, "%s[%s]", Sexp_variables[i].variable_name, Sexp_variables[i].text);
|
||||
m_set_from_variables.AddString(buff);
|
||||
string_variable_indices[num_string_variables++] = i;
|
||||
}
|
||||
}
|
||||
m_set_from_variables.SetCurSel(0);
|
||||
if (!num_string_variables) {
|
||||
m_set_from_variables.EnableWindow(FALSE);
|
||||
}
|
||||
|
||||
// Fill the ship classes combo box
|
||||
m_set_from_ship_class.ResetContent();
|
||||
// Add the default entry if we need one followed by all the ship classes
|
||||
if (num_string_variables) {
|
||||
m_set_from_ship_class.AddString("Set From Variable");
|
||||
}
|
||||
count = 0;
|
||||
for (i=0; i<Num_ship_classes; i++)
|
||||
{
|
||||
if (player_ships_only && !(Ship_info[i].flags & SIF_PLAYER_SHIP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Set up the actual list of alt classes
|
||||
alt_class_pool.clear();
|
||||
alt_class_pool = Ships[Objects[cur_object_index].instance].s_alt_classes;
|
||||
alt_class_list_rebuild();
|
||||
|
||||
return TRUE; // return TRUE unless you set the focus to a control
|
||||
// EXCEPTION: OCX Property Pages should return FALSE
|
||||
}
|
||||
|
||||
|
||||
void AltShipClassDlg::alt_class_list_rebuild()
|
||||
{
|
||||
int i, j;
|
||||
char buff[TOKEN_LENGTH + TOKEN_LENGTH + 2]; // VariableName[VariableValue]
|
||||
|
||||
j = m_alt_class_list.GetCount();
|
||||
for ( i=0; i < j ; i++) {
|
||||
m_alt_class_list.DeleteString(0);
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)alt_class_pool.size() ; i++) {
|
||||
// Default classes should be at the end of the list
|
||||
if(alt_class_pool[i].default_to_this_class && (i < (int)alt_class_pool.size() - 1) ) {
|
||||
// Int3();
|
||||
// TO DO : we should fix this.
|
||||
}
|
||||
|
||||
if (alt_class_pool[i].variable_index != -1) {
|
||||
Assert (alt_class_pool[i].variable_index > -1 && alt_class_pool[i].variable_index < MAX_SEXP_VARIABLES);
|
||||
Assert (Sexp_variables[alt_class_pool[i].variable_index].type & SEXP_VARIABLE_STRING);
|
||||
|
||||
sprintf(buff, "%s[%s]", Sexp_variables[alt_class_pool[i].variable_index].variable_name, Sexp_variables[alt_class_pool[i].variable_index].text);
|
||||
|
||||
// add it to the list
|
||||
m_alt_class_list.AddString(buff);
|
||||
}
|
||||
else {
|
||||
if (alt_class_pool[i].ship_class >= 0 && alt_class_pool[i].ship_class < MAX_SHIP_CLASSES) {
|
||||
m_alt_class_list.AddString(Ship_info[alt_class_pool[i].ship_class].name);
|
||||
}
|
||||
else {
|
||||
m_alt_class_list.AddString("Invalid Ship Class");
|
||||
Int3();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnCancel()
|
||||
{
|
||||
// TODO: Add extra cleanup here
|
||||
|
||||
CDialog::OnCancel();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnOK()
|
||||
{
|
||||
// TODO: Add extra validation here
|
||||
|
||||
for (int i=0; i < num_selected_ships; i++) {
|
||||
Ships[m_selected_ships[i]].s_alt_classes = alt_class_pool;
|
||||
}
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassAdd()
|
||||
{
|
||||
alt_class new_list_item;
|
||||
|
||||
alt_class_update_entry(new_list_item);
|
||||
|
||||
alt_class_pool.push_back(new_list_item);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassInsert()
|
||||
{
|
||||
int index;
|
||||
alt_class new_list_item;
|
||||
alt_class_update_entry(new_list_item);
|
||||
|
||||
index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// If nothing is selected just add it
|
||||
if ( index == -1) {
|
||||
alt_class_pool.push_back(new_list_item);
|
||||
}
|
||||
// Stick it in front of the current selection
|
||||
else {
|
||||
alt_class_pool.insert(alt_class_pool.begin() + index, new_list_item );
|
||||
}
|
||||
|
||||
alt_class_list_rebuild();
|
||||
|
||||
// If we inserted the user will probably want to edit the selection
|
||||
if (index > -1) {
|
||||
m_alt_class_list.SetCurSel(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the currently selected list entry
|
||||
void AltShipClassDlg::alt_class_update_entry(alt_class &list_item)
|
||||
{
|
||||
int index;
|
||||
|
||||
// Add a string variable to the list
|
||||
if (num_string_variables && m_set_from_variables.GetCurSel() > 0) {
|
||||
index = string_variable_indices[m_set_from_variables.GetCurSel() -1];
|
||||
|
||||
Assert (index >= 0);
|
||||
list_item.variable_index = index;
|
||||
list_item.ship_class = ship_info_lookup(Sexp_variables[index].text);
|
||||
}
|
||||
// Add a ship class to the list
|
||||
else {
|
||||
index = m_set_from_ship_class.GetCurSel();
|
||||
|
||||
// Correct the index if the first entry isn't actually a ship class
|
||||
if (num_string_variables) {
|
||||
Assert (index > 0);
|
||||
index--;
|
||||
}
|
||||
|
||||
list_item.variable_index = -1;
|
||||
list_item.ship_class = ship_class_indices[index];
|
||||
}
|
||||
|
||||
// check the default tickbox
|
||||
list_item.default_to_this_class = m_default_to_class.GetCheck() ? true:false;
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnAltClassDelete()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert (index < (int) alt_class_pool.size());
|
||||
alt_class_pool.erase(alt_class_pool.begin()+index);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnMoveUp()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected or already at the top
|
||||
if (index < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap(alt_class_pool[index], alt_class_pool[index-1]);
|
||||
alt_class_list_rebuild();
|
||||
m_alt_class_list.SetCurSel(index-1);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnMoveDown()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected or already at the bottom
|
||||
if (index == -1 || (index >= m_alt_class_list.GetCount() - 1) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::swap(alt_class_pool[index], alt_class_pool[index++]);
|
||||
alt_class_list_rebuild();
|
||||
m_alt_class_list.SetCurSel(index);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelendokSetFromShipClass()
|
||||
{
|
||||
int current_selection;
|
||||
|
||||
if (m_set_from_ship_class.GetCurSel() == 0 && num_string_variables) {
|
||||
m_set_from_variables.SetCurSel(1);
|
||||
}
|
||||
else {
|
||||
m_set_from_variables.SetCurSel(0);
|
||||
}
|
||||
|
||||
// if a list entry is selected we should update it
|
||||
current_selection = m_alt_class_list.GetCurSel();
|
||||
if (current_selection >= 0) {
|
||||
alt_class_update_entry(alt_class_pool[m_alt_class_list.GetCurSel()]);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelendokSetFromVariables()
|
||||
{
|
||||
int current_selection;
|
||||
|
||||
if (m_set_from_variables.GetCurSel() == 0) {
|
||||
m_set_from_ship_class.SetCurSel(num_string_variables ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
m_set_from_ship_class.SetCurSel(0);
|
||||
}
|
||||
|
||||
// if a list entry is selected we should update it
|
||||
current_selection = m_alt_class_list.GetCurSel();
|
||||
if (current_selection >= 0) {
|
||||
alt_class_update_entry(alt_class_pool[m_alt_class_list.GetCurSel()]);
|
||||
alt_class_list_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnSelchangeAltClassList()
|
||||
{
|
||||
int i;
|
||||
int variable_selection = 0;
|
||||
int ship_selection = 0;
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Selected nothing
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a variable selected
|
||||
if (alt_class_pool[index].variable_index != -1) {
|
||||
for (i=0; i < MAX_SEXP_VARIABLES; i++)
|
||||
{
|
||||
if (string_variable_indices[i] == alt_class_pool[index].variable_index) {
|
||||
variable_selection = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ship selected
|
||||
else {
|
||||
for (i=0; i < MAX_SHIP_CLASSES; i++) {
|
||||
if (ship_class_indices[i] == alt_class_pool[index].ship_class) {
|
||||
ship_selection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have string variables in the mission the first entry on the list won't be a ship
|
||||
if (num_string_variables) {
|
||||
ship_selection++;
|
||||
}
|
||||
}
|
||||
|
||||
m_set_from_variables.SetCurSel(variable_selection);
|
||||
m_set_from_ship_class.SetCurSel(ship_selection);
|
||||
m_default_to_class.SetCheck(alt_class_pool[index].default_to_this_class ? 1:0);
|
||||
}
|
||||
|
||||
void AltShipClassDlg::OnDefaultToClass()
|
||||
{
|
||||
int index = m_alt_class_list.GetCurSel();
|
||||
|
||||
// Nothing selected
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
alt_class_pool[index].default_to_this_class = m_default_to_class.GetCheck() ? true:false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
/*
|
||||
* Created by Hassan "Karajorma" Kazmi for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_)
|
||||
#define AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// AltShipClassDlg.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg dialog
|
||||
|
||||
class AltShipClassDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
AltShipClassDlg(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(AltShipClassDlg)
|
||||
enum { IDD = IDD_ALT_SHIP_CLASS };
|
||||
CButton m_default_to_class;
|
||||
CListBox m_alt_class_list;
|
||||
CComboBox m_set_from_ship_class;
|
||||
CComboBox m_set_from_variables;
|
||||
int m_selected_variable;
|
||||
int m_selected_class;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(AltShipClassDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(AltShipClassDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnCancel();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnAltClassAdd();
|
||||
afx_msg void OnAltClassInsert();
|
||||
afx_msg void OnAltClassDelete();
|
||||
afx_msg void OnMoveUp();
|
||||
afx_msg void OnMoveDown();
|
||||
afx_msg void OnSelendokSetFromShipClass();
|
||||
afx_msg void OnSelendokSetFromVariables();
|
||||
afx_msg void OnSelchangeAltClassList();
|
||||
afx_msg void OnDefaultToClass();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
private:
|
||||
|
||||
bool player_ships_only; // Whether we only add player ships to the alt classes or if we can add any ship
|
||||
|
||||
SCP_vector<alt_class> alt_class_pool;
|
||||
int num_string_variables; // Number of string variables in the mission
|
||||
int string_variable_indices[MAX_SEXP_VARIABLES]; // maps string variables to their index in Sexp_variables
|
||||
int ship_class_indices[MAX_SHIP_CLASSES]; // maps ships in the ships combobox to their index in Ship_info
|
||||
|
||||
|
||||
// variables to handle selection of multiple ships
|
||||
bool multi_edit;
|
||||
int m_selected_ships[MAX_SHIPS];
|
||||
int num_selected_ships;
|
||||
|
||||
void AltShipClassDlg::alt_class_list_rebuild();
|
||||
void AltShipClassDlg::alt_class_update_entry(alt_class &list_item);
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_)
|
||||
/*
|
||||
* Created by Hassan "Karajorma" Kazmi for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
#if !defined(AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_)
|
||||
#define AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// AltShipClassDlg.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// AltShipClassDlg dialog
|
||||
|
||||
class AltShipClassDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
AltShipClassDlg(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(AltShipClassDlg)
|
||||
enum { IDD = IDD_ALT_SHIP_CLASS };
|
||||
CButton m_default_to_class;
|
||||
CListBox m_alt_class_list;
|
||||
CComboBox m_set_from_ship_class;
|
||||
CComboBox m_set_from_variables;
|
||||
int m_selected_variable;
|
||||
int m_selected_class;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(AltShipClassDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(AltShipClassDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
virtual void OnCancel();
|
||||
virtual void OnOK();
|
||||
afx_msg void OnAltClassAdd();
|
||||
afx_msg void OnAltClassInsert();
|
||||
afx_msg void OnAltClassDelete();
|
||||
afx_msg void OnMoveUp();
|
||||
afx_msg void OnMoveDown();
|
||||
afx_msg void OnSelendokSetFromShipClass();
|
||||
afx_msg void OnSelendokSetFromVariables();
|
||||
afx_msg void OnSelchangeAltClassList();
|
||||
afx_msg void OnDefaultToClass();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
|
||||
private:
|
||||
|
||||
bool player_ships_only; // Whether we only add player ships to the alt classes or if we can add any ship
|
||||
|
||||
SCP_vector<alt_class> alt_class_pool;
|
||||
int num_string_variables; // Number of string variables in the mission
|
||||
int string_variable_indices[MAX_SEXP_VARIABLES]; // maps string variables to their index in Sexp_variables
|
||||
int ship_class_indices[MAX_SHIP_CLASSES]; // maps ships in the ships combobox to their index in Ship_info
|
||||
|
||||
|
||||
// variables to handle selection of multiple ships
|
||||
bool multi_edit;
|
||||
int m_selected_ships[MAX_SHIPS];
|
||||
int num_selected_ships;
|
||||
|
||||
void AltShipClassDlg::alt_class_list_rebuild();
|
||||
void AltShipClassDlg::alt_class_update_entry(alt_class &list_item);
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_AltShipClassDlg_H__2FE2C917_C7DA_4C05_A11F_DCC46BFB26BB__INCLUDED_)
|
||||
+116
-144
@@ -1,144 +1,116 @@
|
||||
// FictionViewerDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "fred.h"
|
||||
#include "FictionViewerDlg.h"
|
||||
#include "missionui/fictionviewer.h"
|
||||
#include "gamesnd/eventmusic.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg dialog
|
||||
|
||||
|
||||
FictionViewerDlg::FictionViewerDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(FictionViewerDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(FictionViewerDlg)
|
||||
m_story_file = _T("");
|
||||
m_font_file = _T("");
|
||||
m_voice_file = _T("");
|
||||
m_fiction_music = 0;
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void FictionViewerDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(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
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(FictionViewerDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(FictionViewerDlg)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg message handlers
|
||||
|
||||
BOOL FictionViewerDlg::OnInitDialog()
|
||||
{
|
||||
int i;
|
||||
CComboBox *box;
|
||||
|
||||
box = (CComboBox *) GetDlgItem(IDC_FICTION_MUSIC);
|
||||
box->AddString("None");
|
||||
for (i=0; i<Num_music_files; i++){
|
||||
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
|
||||
m_fiction_music = Mission_music[SCORE_FICTION_VIEWER] + 1;
|
||||
|
||||
CDialog::OnInitDialog();
|
||||
UpdateData(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// set music
|
||||
Mission_music[SCORE_FICTION_VIEWER] = m_fiction_music - 1;
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
|
||||
void FictionViewerDlg::OnCancel()
|
||||
{
|
||||
// TODO: Add extra cleanup here
|
||||
|
||||
CDialog::OnCancel();
|
||||
}
|
||||
|
||||
void FictionViewerDlg::OnClose()
|
||||
{
|
||||
int z;
|
||||
|
||||
UpdateData(TRUE);
|
||||
|
||||
if (query_modified()) {
|
||||
z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
|
||||
if (z == IDCANCEL){
|
||||
return;
|
||||
}
|
||||
|
||||
if (z == IDYES) {
|
||||
OnOK();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CDialog::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);
|
||||
}
|
||||
// FictionViewerDlg.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "fred.h"
|
||||
#include "FictionViewerDlg.h"
|
||||
#include "missionui/fictionviewer.h"
|
||||
#include "gamesnd/eventmusic.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg dialog
|
||||
|
||||
|
||||
FictionViewerDlg::FictionViewerDlg(CWnd* pParent /*=NULL*/)
|
||||
: CDialog(FictionViewerDlg::IDD, pParent)
|
||||
{
|
||||
//{{AFX_DATA_INIT(FictionViewerDlg)
|
||||
m_story_file = _T("");
|
||||
m_font_file = _T("");
|
||||
m_fiction_music = 0;
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
||||
void FictionViewerDlg::DoDataExchange(CDataExchange* pDX)
|
||||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(FictionViewerDlg)
|
||||
DDX_Text(pDX, IDC_STORY_FILE, m_story_file);
|
||||
DDX_Text(pDX, IDC_FONT_FILE, m_font_file);
|
||||
DDX_CBIndex(pDX, IDC_FICTION_MUSIC, m_fiction_music);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(FictionViewerDlg, CDialog)
|
||||
//{{AFX_MSG_MAP(FictionViewerDlg)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg message handlers
|
||||
|
||||
BOOL FictionViewerDlg::OnInitDialog()
|
||||
{
|
||||
int i;
|
||||
CComboBox *box;
|
||||
|
||||
box = (CComboBox *) GetDlgItem(IDC_FICTION_MUSIC);
|
||||
box->AddString("None");
|
||||
for (i=0; i<Num_music_files; i++){
|
||||
box->AddString(Spooled_music[i].name);
|
||||
}
|
||||
|
||||
// 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();
|
||||
UpdateData(FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void FictionViewerDlg::OnOK()
|
||||
{
|
||||
UpdateData(TRUE);
|
||||
|
||||
// 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;
|
||||
|
||||
CDialog::OnOK();
|
||||
}
|
||||
|
||||
void FictionViewerDlg::OnCancel()
|
||||
{
|
||||
// TODO: Add extra cleanup here
|
||||
|
||||
CDialog::OnCancel();
|
||||
}
|
||||
|
||||
void FictionViewerDlg::OnClose()
|
||||
{
|
||||
int z;
|
||||
|
||||
UpdateData(TRUE);
|
||||
|
||||
if (query_modified()) {
|
||||
z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
|
||||
if (z == IDCANCEL){
|
||||
return;
|
||||
}
|
||||
|
||||
if (z == IDYES) {
|
||||
OnOK();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CDialog::OnClose();
|
||||
}
|
||||
|
||||
int FictionViewerDlg::query_modified()
|
||||
{
|
||||
return strcmp(m_story_file, fiction_file()) || strcmp(m_font_file, fiction_font()) || m_fiction_music != (Mission_music[SCORE_FICTION_VIEWER] + 1);
|
||||
}
|
||||
@@ -1,56 +1,52 @@
|
||||
#if !defined(AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_)
|
||||
#define AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// FictionViewerDlg.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg dialog
|
||||
|
||||
class FictionViewerDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
FictionViewerDlg(CWnd* pParent = NULL); // standard constructor
|
||||
int query_modified();
|
||||
void OnOK();
|
||||
void OnCancel();
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(FictionViewerDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(FictionViewerDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnClose();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_)
|
||||
#if !defined(AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_)
|
||||
#define AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
// FictionViewerDlg.h : header file
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FictionViewerDlg dialog
|
||||
|
||||
class FictionViewerDlg : public CDialog
|
||||
{
|
||||
// Construction
|
||||
public:
|
||||
FictionViewerDlg(CWnd* pParent = NULL); // standard constructor
|
||||
int query_modified();
|
||||
void OnOK();
|
||||
void OnCancel();
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(FictionViewerDlg)
|
||||
enum { IDD = IDD_FICTION_VIEWER };
|
||||
CString m_story_file;
|
||||
CString m_font_file;
|
||||
int m_fiction_music;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
// Overrides
|
||||
// ClassWizard generated virtual function overrides
|
||||
//{{AFX_VIRTUAL(FictionViewerDlg)
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
|
||||
//}}AFX_VIRTUAL
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
|
||||
// Generated message map functions
|
||||
//{{AFX_MSG(FictionViewerDlg)
|
||||
virtual BOOL OnInitDialog();
|
||||
afx_msg void OnClose();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_FICTIONVIEWERDLG_H__46BAD1B6_F9DC_4414_9C33_18EC17FD491F__INCLUDED_)
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "parse/sexp.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
@@ -153,7 +154,7 @@ void CAddVariableDlg::validate_variable_name(int set_focus)
|
||||
|
||||
// Check if any change and not already in list
|
||||
if ( stricmp(temp_name, "<Variable Name>") ) {
|
||||
if ( (strlen(temp_name) > 0) && (get_index_sexp_variable_name(LPCTSTR(temp_name)) == -1) ) { //not already in list and length > 0 { //-V805
|
||||
if ( (strlen(temp_name) > 0) && (get_index_sexp_variable_name(LPCTSTR(temp_name)) == -1) ) { //not already in list and length > 0 {
|
||||
// Goober5000 - replace spaces with hyphens
|
||||
if (strchr(temp_name, ' ') != NULL)
|
||||
{
|
||||
@@ -174,7 +175,7 @@ void CAddVariableDlg::validate_variable_name(int set_focus)
|
||||
m_name_validated = true;
|
||||
} else {
|
||||
// conflicting variable name
|
||||
if (strlen(temp_name) == 0) { //-V805
|
||||
if (strlen(temp_name) == 0) {
|
||||
edit->SetWindowText("<Variable Name>");
|
||||
}
|
||||
m_name_validated = false;
|
||||
@@ -204,7 +205,7 @@ void CAddVariableDlg::validate_data(int set_focus)
|
||||
edit->GetWindowText(temp_data);
|
||||
|
||||
// check for 0 string length
|
||||
if (strlen(temp_data) == 0) { //-V805
|
||||
if (strlen(temp_data) == 0) {
|
||||
m_data_validated = false;
|
||||
} else {
|
||||
if (m_type_number) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "mission/missiongrid.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "species_defs/species_defs.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
@@ -440,7 +441,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
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "ship/ship.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
Loaded 100 of 1122 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user