--- /dev/null
+Microsoft Visual Studio Solution File, Format Version 8.00\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lugaru", "Lugaru.vcproj", "{71D87E45-76A7-497F-9176-DA2600007A65}"\r
+ ProjectSection(ProjectDependencies) = postProject\r
+ EndProjectSection\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfiguration) = preSolution\r
+ Debug = Debug\r
+ Release = Release\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfiguration) = postSolution\r
+ {71D87E45-76A7-497F-9176-DA2600007A65}.Debug.ActiveCfg = Debug|Win32\r
+ {71D87E45-76A7-497F-9176-DA2600007A65}.Debug.Build.0 = Debug|Win32\r
+ {71D87E45-76A7-497F-9176-DA2600007A65}.Release.ActiveCfg = Release|Win32\r
+ {71D87E45-76A7-497F-9176-DA2600007A65}.Release.Build.0 = Release|Win32\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityGlobals) = postSolution\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityAddIns) = postSolution\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="7.10"\r
+ Name="Lugaru"\r
+ ProjectGUID="{71D87E45-76A7-497F-9176-DA2600007A65}"\r
+ RootNamespace="Lugaru"\r
+ Keyword="Win32Proj">\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"/>\r
+ </Platforms>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="Debug"\r
+ IntermediateDirectory="Debug"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories="./Source;./Source/devil/include"\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"\r
+ MinimalRebuild="TRUE"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="5"\r
+ BufferSecurityCheck="TRUE"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="FALSE"\r
+ DebugInformationFormat="4"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/Lugaru.exe"\r
+ LinkIncremental="2"\r
+ GenerateDebugInformation="TRUE"\r
+ ProgramDatabaseFile="$(OutDir)/Lugaru.pdb"\r
+ SubSystem="2"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ <Tool\r
+ Name="VCManagedWrapperGeneratorTool"/>\r
+ <Tool\r
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="Release"\r
+ IntermediateDirectory="Release"\r
+ ConfigurationType="1"\r
+ CharacterSet="2">\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ AdditionalIncludeDirectories="./Source;./Source/devil/include"\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"\r
+ BasicRuntimeChecks="0"\r
+ RuntimeLibrary="4"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="FALSE"\r
+ DebugInformationFormat="3"/>\r
+ <Tool\r
+ Name="VCCustomBuildTool"/>\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="$(OutDir)/Lugaru.exe"\r
+ LinkIncremental="1"\r
+ GenerateDebugInformation="TRUE"\r
+ SubSystem="2"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ TargetMachine="1"/>\r
+ <Tool\r
+ Name="VCMIDLTool"/>\r
+ <Tool\r
+ Name="VCPostBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreBuildEventTool"/>\r
+ <Tool\r
+ Name="VCPreLinkEventTool"/>\r
+ <Tool\r
+ Name="VCResourceCompilerTool"/>\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"/>\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"/>\r
+ <Tool\r
+ Name="VCWebDeploymentTool"/>\r
+ <Tool\r
+ Name="VCManagedWrapperGeneratorTool"/>\r
+ <Tool\r
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">\r
+ <File\r
+ RelativePath=".\Source\Frustum.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\GameDraw.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\GameInitDispose.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\GameTick.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Globals.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Lights.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Models.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Objects.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\OpenGL_Windows.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\pack.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\pack_private.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Person.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\private.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Quaternions.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Random.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Skeleton.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Skybox.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Sprites.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Terrain.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Text.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\TGALoader.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\unpack.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\unpack_private.c">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Weapons.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\WinDefs.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\WinInput.cpp">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">\r
+ <File\r
+ RelativePath=".\Source\binio.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Constants.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Frustum.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Game.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\gl.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Lights.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\LinkedList.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\md5.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Models.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Objects.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\pack_private.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Person.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\PhysicsMath.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Pointer.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\private.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Quaternions.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Random.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Skeleton.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Skybox.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Sprites.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Terrain.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Text.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\TGALoader.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\unpack_private.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Weapons.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\wincompat.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\WinDefs.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\WinInput.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">\r
+ <File\r
+ RelativePath=".\Source\res\lugaru.ico">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\res\Lugaru.rc">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\res\resource.h">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="fmod"\r
+ Filter="">\r
+ <File\r
+ RelativePath=".\Source\fmod.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\fmod_errors.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\fmod_header.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\fmoddyn.h">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\fmodvc.lib">\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="devil"\r
+ Filter="">\r
+ <Filter\r
+ Name="lib"\r
+ Filter="">\r
+ <File\r
+ RelativePath=".\Source\devil\lib\DevIL.lib">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\devil\lib\ILU.lib">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\devil\lib\ILUT.lib">\r
+ </File>\r
+ </Filter>\r
+ </Filter>\r
+ <Filter\r
+ Name="logger"\r
+ Filter="">\r
+ <File\r
+ RelativePath=".\Source\logger\logger.cpp">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\logger\logger.h">\r
+ </File>\r
+ </Filter>\r
+ <File\r
+ RelativePath=".\Data\config.txt">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Driver.cc">\r
+ </File>\r
+ <File\r
+ RelativePath=".\Source\Md5.cc">\r
+ </File>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
--- /dev/null
+// Carbon Include.h
+
+// Put Carbon specific stuff here to maintain 9/Carbon buildability...
+
+
+#define TARGET_API_MAC_CARBON 1
\ No newline at end of file
--- /dev/null
+/*\r * Permit this Carbon application to launch on OS X\r *\r * Copyright © 1997-2001 Metrowerks Corporation\r *\r * Questions and comments to:\r * <mailto:support@metrowerks.com>\r * <http://www.metrowerks.com/>\r */\r\r\r\r/*----------------------------carb ¥ Carbon on OS X launch information --------------------------*/\rtype 'carb' {\r};\r\r\rresource 'carb'(0) {\r};
\ No newline at end of file
--- /dev/null
+/************************************************************
+
+ CarbonStdCLib.h
+ Assorted helper functions associated with CarbonStdClib.o.
+
+ Copyright Apple Computer,Inc. 2001
+ All rights reserved
+
+ * Warning: This interface is NOT a part of the ANSI C standard.
+ * This header file is not POSIX compliant.
+ * For portable code, don't use this interface.
+
+************************************************************/
+
+
+#ifndef __CARBONSTDCLIB__
+#define __CARBONSTDCLIB__
+
+#ifndef __CONDITIONALMACROS__
+#include <ConditionalMacros.h>
+#endif
+
+#if defined (__powerc) || defined (powerc) || defined (__CFM68K__)
+ #pragma import on
+#endif
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if !(CALL_NOT_IN_CARBON || __MPWINTERNAL__)
+
+extern void InitCarbonStdCLib( void ) ;
+extern void TermCarbonStdCLib( void ) ;
+
+extern void ConvertUnixPathToHFSPath(const char *unixPath, char *hfsPath) ;
+extern void ConvertHFSPathToUnixPath(const char *hfsPath, char *unixPath) ;
+
+/* BSD functions */
+
+int bsd_chdir(const char *path) ;
+int bsd_chmod(const char *path , int mode) ;
+
+#endif
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#if defined (__powerc) || defined (powerc) || defined (__CFM68K__)
+ #pragma import off
+#endif
+
+#endif /* __CARBONSTDCLIB__ */
--- /dev/null
+#ifndef _CONSTANTS_H_
+#define _CONSTANTS_H_
+
+#define awardklutz 0
+#define awardflawless 1
+#define awardalldead 2
+#define awardnodead 3
+#define awardstealth 4
+#define awardswordsman 5
+#define awardkungfu 6
+#define awardknifefighter 7
+#define awardcoward 8
+#define awardevasion 9
+#define awardacrobat 10
+#define awardlongrange 11
+#define awardbrutal 12
+#define awardhyper 13
+#define awardaikido 14
+#define awardrambo 15
+#define awardfast 16
+#define awardrealfast 17
+#define awarddamnfast 18
+#define awardstrategy 19
+#define awardbojutsu 20
+
+#define mapkilleveryone 0
+#define mapgosomewhere 1
+#define mapkillsomeone 2
+#define mapkillmost 3
+
+#define wpkeepwalking 0
+#define wppause 1
+
+#define typeactive 0
+#define typesitting 1
+#define typesittingwall 2
+#define typesleeping 3
+#define typedead1 4
+#define typedead2 5
+#define typedead3 6
+#define typedead4 7
+
+#define tracheotomy 1
+#define backstab 2
+#define spinecrusher 3
+#define ninja 4
+#define style 5
+#define cannon 6
+#define aimbonus 7
+#define deepimpact 8
+#define touchofdeath 9
+#define swordreversebonus 10
+#define staffreversebonus 11
+#define reverseko 12
+#define solidhit 13
+#define twoxcombo 14
+#define threexcombo 15
+#define fourxcombo 16
+#define megacombo 17
+#define Reversal 18
+#define Stabbonus 19
+#define Slicebonus 20
+#define Bullseyebonus 21
+#define Slashbonus 22
+#define Wolfbonus 23
+#define FinishedBonus 24
+#define TackleBonus 25
+#define AboveBonus 26
+
+#define boneconnect 0
+#define constraint 1
+#define muscle 2
+
+#define head 0
+#define neck 1
+#define leftshoulder 2
+#define leftelbow 3
+#define leftwrist 4
+#define lefthand 5
+#define rightshoulder 6
+#define rightelbow 7
+#define rightwrist 8
+#define righthand 9
+#define abdomen 10
+#define lefthip 11
+#define righthip 12
+#define groin 13
+#define leftknee 14
+#define leftankle 15
+#define leftfoot 16
+#define rightknee 17
+#define rightankle 18
+#define rightfoot 19
+
+#define max_joints 50
+#define max_frames 50
+#define max_muscles 100
+
+#define animation_count 140
+
+#define runanim 0
+#define bounceidleanim 1
+#define stopanim 2
+#define jumpupanim 3
+#define jumpdownanim 4
+#define landanim 5
+#define climbanim 6
+#define hanganim 7
+#define spinkickanim 8
+#define tempanim 9
+#define getupfromfrontanim 10
+#define getupfrombackanim 11
+#define crouchanim 12
+#define sneakanim 13
+#define rollanim 14
+#define flipanim 15
+#define spinkickreversedanim 16
+#define spinkickreversalanim 17
+#define lowkickanim 18
+#define sweepanim 19
+#define sweepreversedanim 20
+#define sweepreversalanim 21
+#define rabbitkickanim 22
+#define rabbitkickreversedanim 23
+#define rabbitkickreversalanim 24
+#define upunchanim 25
+#define staggerbackhighanim 26
+#define upunchreversedanim 27
+#define upunchreversalanim 28
+#define hurtidleanim 29
+#define backhandspringanim 30
+#define fightidleanim 31
+#define walkanim 32
+#define fightsidestep 33
+#define killanim 34
+#define sneakattackanim 35
+#define sneakattackedanim 36
+#define drawrightanim 37
+#define knifeslashstartanim 38
+#define crouchstabanim 39
+#define crouchdrawrightanim 40
+#define knifefollowanim 41
+#define knifefollowedanim 42
+#define knifethrowanim 43
+#define removeknifeanim 44
+#define crouchremoveknifeanim 45
+#define jumpreversedanim 46
+#define jumpreversalanim 47
+#define landhardanim 48
+#define staggerbackhardanim 49
+#define dropkickanim 50
+#define winduppunchanim 51
+#define winduppunchblockedanim 52
+#define blockhighleftanim 53
+#define blockhighleftstrikeanim 54
+#define walljumpfrontanim 55
+#define walljumpbackanim 56
+#define walljumpleftanim 57
+#define walljumprightanim 58
+#define backflipanim 59
+#define leftflipanim 60
+#define rightflipanim 61
+#define walljumprightkickanim 62
+#define walljumpleftkickanim 63
+#define knifefightidleanim 64
+#define knifesneakattackanim 65
+#define knifesneakattackedanim 66
+#define swordstabanim 67
+#define swordslashleftanim 68
+#define swordslashrightanim 69
+#define swordfightidleanim 70
+#define swordsneakattackanim 71
+#define swordsneakattackedanim 72
+#define drawleftanim 73
+#define swordslashanim 74
+#define swordgroundstabanim 75
+#define dodgebackanim 76
+#define swordslashreversedanim 77
+#define swordslashreversalanim 78
+#define knifeslashreversedanim 79
+#define knifeslashreversalanim 80
+#define swordfightidlebothanim 81
+#define swordslashparryanim 82
+#define sworddisarmanim 83
+#define swordslashparriedanim 84
+#define wolfidle 85
+#define wolffightidle 86
+#define wolfswordidle 87
+#define wolfhurtidle 88
+#define wolfcrouchanim 89
+#define wolfsneakanim 90
+#define wolfrunanim 91
+#define wolfstopanim 92
+#define wolfclawanim 93
+#define wolflandanim 94
+#define wolflandhardanim 95
+#define wolfrunninganim 96
+#define rabbitrunninganim 97
+#define frontflipanim 98
+#define rabbittackleanim 99
+#define rabbittacklinganim 100
+#define rabbittackledfrontanim 101
+#define rabbittackledbackanim 102
+#define rabbittacklereversal 103
+#define rabbittacklereversed 104
+#define wolftackleanim 105
+#define wolftacklinganim 106
+#define wolftackledfrontanim 107
+#define wolftackledbacanim 108
+#define wolftacklereversal 109
+#define wolftacklereversed 110
+#define wolfslapanim 111
+#define wolfbashanim 112
+#define staffhitanim 113
+#define staffgroundsmashanim 114
+#define staffspinhitanim 115
+#define staffhitreversedanim 116
+#define staffhitreversalanim 117
+#define staffspinhitreversedanim 118
+#define staffspinhitreversalanim 119
+#define sleepanim 120
+#define sitanim 121
+#define talkidleanim 122
+#define sitwallanim 123
+#define dead1anim 124
+#define dead2anim 125
+#define dead3anim 126
+#define dead4anim 127
+
+#define max_dialogues 20
+#define max_dialoguelength 20
+
+#define max_model_vertex 3000 // maximum number of vertexs
+#define max_textured_triangle 3000 // maximum number of texture-filled triangles in a model
+
+#define stream_music1desert 0
+#define stream_music1grass 1
+#define stream_music1snow 2
+#define stream_music2 3
+#define stream_music3 4
+#define stream_music4 5
+#define stream_menumusic 6
+#define stream_desertambient 7
+#define stream_firesound 8
+#define stream_wind 9
+
+//#define music1desert 0
+//#define music1grass 1
+//#define music1snow 2
+//#define music2 3
+//#define music3 4
+//#define music4 5
+//#define menumusic 6
+//#define desertambient 7
+//#define firesound 8
+//#define wind 9
+#define footstepsound 10
+#define footstepsound2 11
+#define footstepsound3 12
+#define footstepsound4 13
+#define jumpsound 14
+#define landsound 15
+#define whooshsound 16
+#define hawksound 17
+#define landsound1 18
+#define landsound2 19
+#define breaksound 20
+#define lowwhooshsound 21
+#define heavyimpactsound 22
+#define firestartsound 23
+#define fireendsound 24
+#define breaksound2 25
+#define knifedrawsound 26
+#define knifesheathesound 27
+#define knifeswishsound 28
+#define knifeslicesound 29
+#define skidsound 30
+#define snowskidsound 31
+#define bushrustle 32
+#define midwhooshsound 33
+#define highwhooshsound 34
+#define movewhooshsound 35
+#define thudsound 36
+#define whooshhitsound 37
+#define clank1sound 38
+#define clank2sound 39
+#define clank3sound 40
+#define clank4sound 41
+#define consolefailsound 42
+#define consolesuccesssound 43
+#define swordslicesound 44
+#define metalhitsound 45
+#define clawslicesound 46
+#define splattersound 47
+#define growlsound 48
+#define growl2sound 49
+#define barksound 50
+#define snarlsound 51
+#define snarl2sound 52
+#define barkgrowlsound 53
+#define bark2sound 54
+#define bark3sound 55
+#define rabbitattacksound 56
+#define rabbitattack2sound 57
+#define rabbitattack3sound 58
+#define rabbitattack4sound 59
+#define rabbitpainsound 60
+#define rabbitpain1sound 61
+#define rabbitpain2sound 62
+#define rabbitchitter 63
+#define rabbitchitter2 64
+#define fleshstabsound 65
+#define fleshstabremovesound 66
+#define swordstaffsound 67
+#define staffbodysound 68
+#define staffheadsound 69
+#define alarmsound 70
+#define staffbreaksound 71
+
+#define normalmode 0
+#define motionblurmode 1
+#define radialzoommode 2
+#define realmotionblurmode 3
+#define doublevisionmode 4
+#define glowmode 5
+
+#define maxplayers 10
+#endif
\ No newline at end of file
--- /dev/null
+// DRIVER.CC - test driver for the C++/object oriented translation and
+// modification of MD5.
+
+// Translation and modification (c) 1995 by Mordechai T. Abzug
+
+// This translation/ modification is provided "as is," without express or
+// implied warranty of any kind.
+
+// The translator/ modifier does not claim (1) that MD5 will do what you think
+// it does; (2) that this translation/ modification is accurate; or (3) that
+// this software is "merchantible." (Language for this disclaimer partially
+// copied from the disclaimer below).
+
+/* based on:
+
+ MDDRIVER.C - test driver for MD2, MD4 and MD5
+
+ Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+rights reserved.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+#include "md5.h"
+
+
+// Length of test block, number of test blocks.
+
+#define TEST_BLOCK_LEN 1000
+#define TEST_BLOCK_COUNT 1000
+
+static void MD5_timeTrial (void);
+static void MD5_testSuite (void);
+static void MD5_file (char *);
+static void MD5_filter (void);
+static void MD5_string (unsigned char *string);
+static char *MD5_usage (void);
+
+// Main driver.
+/*
+int main (int argc, char *argv[]){
+
+ int i;
+
+ MD5_testSuite();
+
+ if (argc > 1)
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 's')
+ MD5_string ( (unsigned char *) argv[i] + 2);
+ else if (strcmp (argv[i], "-t") == 0)
+ MD5_timeTrial ();
+ else if (strcmp (argv[i], "-x") == 0)
+ MD5_testSuite ();
+ else if (strcmp (argv[i], "-h") == 0)
+ cout << MD5_usage()<< flush;
+ else if (strcmp (argv[i], "-help")==0)
+ cout << MD5_usage()<< flush;
+ else if (argv[i][0] == '-'){
+ cerr << argv[i] << " is an unknown option.\n" << MD5_usage()<< flush;
+ exit (1);
+ }
+ else
+ MD5_file (argv[i]);
+ else
+ MD5_filter ();
+
+ return (0);
+}
+*/
+
+// Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks.
+
+static void MD5_timeTrial ()
+{
+ MD5 context;
+ time_t endTime, startTime;
+ unsigned char block[TEST_BLOCK_LEN];
+ unsigned int i;
+
+
+ cout << "MD5 time trial. Digesting "<< TEST_BLOCK_LEN << " ";
+ cout << TEST_BLOCK_COUNT << "-byte blocks ...";
+
+ // Initialize block
+ for (i = 0; i < TEST_BLOCK_LEN; i++)
+ block[i] = (unsigned char)(i & 0xff);
+
+ // Start timer
+ time (&startTime);
+
+ // Digest blocks
+ for (i = 0; i < TEST_BLOCK_COUNT; i++)
+ context.update (block, TEST_BLOCK_LEN);
+
+ context.finalize();
+
+ // Stop timer
+ time (&endTime);
+
+ cout << " done" << endl;
+
+ cout << "Digest = " << context << endl;
+
+ cout << "Time = "<< (long)(endTime-startTime) << " seconds" << endl;
+
+ cout << "Speed = ";
+ cout << (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime);
+ cout << "bytes/second" <<endl;
+
+}
+
+// Digests a reference suite of strings and prints the results.
+/*
+static void MD5_testSuite ()
+{
+ cout << "MD5 test suite:" << endl;
+
+ MD5_string ( (unsigned char*) "");
+ MD5_string ( (unsigned char*) "a");
+ MD5_string ( (unsigned char*) "abc");
+ MD5_string ( (unsigned char*) "message digest");
+ MD5_string ( (unsigned char*) "abcdefghijklmnopqrstuvwxyz");
+ MD5_string
+ ( (unsigned char*) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MD5_string
+ ( (unsigned char*) "1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+}
+*/
+
+// Digests a file and prints the result.
+
+static void MD5_file (char *filename){
+
+ ifstream file(filename);
+
+ if (!file)
+ cerr << filename <<" can't be opened" << endl;
+ else {
+ MD5 context(file);
+ cout << "MD5 (" << filename << ") = " << context << endl;
+ }
+}
+
+// Digests the standard input and prints the result.
+
+static void MD5_filter ()
+{
+
+ MD5 context(cin); // ie. run istream version of MD5 on cin.
+ // Could also run file version of MD5 on stdin.
+
+ cout << context << endl;
+}
+
+
+
+// Digests a string and prints the result.
+/*
+void MD5_string (unsigned char *string){
+
+ MD5 context;
+ unsigned int len = strlen ( (char *)string);
+
+ context.update (string, len);
+ context.finalize ();
+
+ cout << "MD5 (\"" << (char *)string << "\") = " << context <<endl;
+}*/
+
+
+
+static char *MD5_usage(){
+
+ return "\n\
+ MD5\n\n\
+USAGE:\n\n\
+ MD5 [-sstring] [-t] [-x] [-h] [-help] [filename]\n\n\
+Arguments (may be any combination):\n\
+ -sstring - digests string\n\
+ -t - runs time trial\n\
+ -x - runs test script\n\
+ -h - displays this message\n\
+ -help - displays this message\n\
+ filename - digests file\n\
+ (none) - digests standard input\n\n";
+}
+
+
+
--- /dev/null
+#include "frustum.h"
+#include <math.h>
+
+#include "gl.h"
+
+
+void FRUSTUM::
+ GetFrustum() {
+ static float projmatrix[16];
+ static float mvmatrix[16];
+ static float clip[16];
+ static float t;
+
+ glGetFloatv(GL_PROJECTION_MATRIX, projmatrix);
+ glGetFloatv(GL_MODELVIEW_MATRIX, mvmatrix);
+
+ // Combine the matrices
+ clip[0] = mvmatrix[0] * projmatrix[0] + mvmatrix[1] * projmatrix[4] + mvmatrix[2] * projmatrix[8] + mvmatrix[3] * projmatrix[12];
+ clip[1] = mvmatrix[0] * projmatrix[1] + mvmatrix[1] * projmatrix[5] + mvmatrix[2] * projmatrix[9] + mvmatrix[3] * projmatrix[13];
+ clip[2] = mvmatrix[0] * projmatrix[2] + mvmatrix[1] * projmatrix[6] + mvmatrix[2] * projmatrix[10] + mvmatrix[3] * projmatrix[14];
+ clip[3] = mvmatrix[0] * projmatrix[3] + mvmatrix[1] * projmatrix[7] + mvmatrix[2] * projmatrix[11] + mvmatrix[3] * projmatrix[15];
+
+ clip[4] = mvmatrix[4] * projmatrix[0] + mvmatrix[5] * projmatrix[4] + mvmatrix[6] * projmatrix[8] + mvmatrix[7] * projmatrix[12];
+ clip[5] = mvmatrix[4] * projmatrix[1] + mvmatrix[5] * projmatrix[5] + mvmatrix[6] * projmatrix[9] + mvmatrix[7] * projmatrix[13];
+ clip[6] = mvmatrix[4] * projmatrix[2] + mvmatrix[5] * projmatrix[6] + mvmatrix[6] * projmatrix[10] + mvmatrix[7] * projmatrix[14];
+ clip[7] = mvmatrix[4] * projmatrix[3] + mvmatrix[5] * projmatrix[7] + mvmatrix[6] * projmatrix[11] + mvmatrix[7] * projmatrix[15];
+
+ clip[8] = mvmatrix[8] * projmatrix[0] + mvmatrix[9] * projmatrix[4] + mvmatrix[10] * projmatrix[8] + mvmatrix[11] * projmatrix[12];
+ clip[9] = mvmatrix[8] * projmatrix[1] + mvmatrix[9] * projmatrix[5] + mvmatrix[10] * projmatrix[9] + mvmatrix[11] * projmatrix[13];
+ clip[10] = mvmatrix[8] * projmatrix[2] + mvmatrix[9] * projmatrix[6] + mvmatrix[10] * projmatrix[10] + mvmatrix[11] * projmatrix[14];
+ clip[11] = mvmatrix[8] * projmatrix[3] + mvmatrix[9] * projmatrix[7] + mvmatrix[10] * projmatrix[11] + mvmatrix[11] * projmatrix[15];
+
+ clip[12] = mvmatrix[12] * projmatrix[0] + mvmatrix[13] * projmatrix[4] + mvmatrix[14] * projmatrix[8] + mvmatrix[15] * projmatrix[12];
+ clip[13] = mvmatrix[12] * projmatrix[1] + mvmatrix[13] * projmatrix[5] + mvmatrix[14] * projmatrix[9] + mvmatrix[15] * projmatrix[13];
+ clip[14] = mvmatrix[12] * projmatrix[2] + mvmatrix[13] * projmatrix[6] + mvmatrix[14] * projmatrix[10] + mvmatrix[15] * projmatrix[14];
+ clip[15] = mvmatrix[12] * projmatrix[3] + mvmatrix[13] * projmatrix[7] + mvmatrix[14] * projmatrix[11] + mvmatrix[15] * projmatrix[15];
+
+ // Right plane
+ frustum[0][0] = clip[3] - clip[0];
+ frustum[0][1] = clip[7] - clip[4];
+ frustum[0][2] = clip[11] - clip[8];
+ frustum[0][3] = clip[15] - clip[12];
+
+ // Left plane
+ frustum[1][0] = clip[3] + clip[0];
+ frustum[1][1] = clip[7] + clip[4];
+ frustum[1][2] = clip[11] + clip[8];
+ frustum[1][3] = clip[15] + clip[12];
+
+ // Bottom plane
+ frustum[2][0] = clip[3] + clip[1];
+ frustum[2][1] = clip[7] + clip[5];
+ frustum[2][2] = clip[11] + clip[9];
+ frustum[2][3] = clip[15] + clip[13];
+
+ // Top plane
+ frustum[3][0] = clip[3] - clip[1];
+ frustum[3][1] = clip[7] - clip[5];
+ frustum[3][2] = clip[11] - clip[9];
+ frustum[3][3] = clip[15] - clip[13];
+
+ // Far plane
+ frustum[4][0] = clip[3] - clip[2];
+ frustum[4][1] = clip[7] - clip[6];
+ frustum[4][2] = clip[11] - clip[10];
+ frustum[4][3] = clip[15] - clip[14];
+
+ // Near plane
+ frustum[5][0] = clip[3] + clip[2];
+ frustum[5][1] = clip[7] + clip[6];
+ frustum[5][2] = clip[11] + clip[10];
+ frustum[5][3] = clip[15] + clip[14];
+}
+
+int FRUSTUM::
+ CubeInFrustum(float x, float y, float z, float size) {
+ static int c, c2;
+
+ for(int i=0; i<6; i++) {
+ c=0;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y-size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y-size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y+size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y+size) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y-size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y-size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y+size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y+size) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(c==0)
+ return 0;
+ if(c==8)
+ c2++;
+ }
+ if(c2>=6)
+ return 2;
+ else
+ return 1;
+}
+
+int FRUSTUM::
+ CubeInFrustum(float x, float y, float z, float size, float height) {
+ static int c, c2;
+
+ for(int i=0; i<6; i++) {
+ c=0;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y-height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y-height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y+height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y+height) + frustum[i][2] * (z-size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y-height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y-height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x-size) + frustum[i][1] * (y+height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(frustum[i][0] * (x+size) + frustum[i][1] * (y+height) + frustum[i][2] * (z+size) + frustum[i][3] > 0)
+ c++;
+ if(c==0)
+ return 0;
+ if(c==8)
+ c2++;
+ }
+ if(c2>=6)
+ return 2;
+ else
+ return 1;
+}
+
+int FRUSTUM::
+ SphereInFrustum(float x, float y, float z, float radius) {
+ static int c2;
+
+ for(int i=0; i<6; i++) {
+ if(frustum[i][0] * x + frustum[i][1] * y + frustum[i][2] * z + frustum[i][3] > -1*radius)
+ c2++;
+ else
+ return 0;
+ }
+ if(c2>=6)
+ return 2;
+ else
+ return 1;
+}
\ No newline at end of file
--- /dev/null
+#ifndef FRUSTUM_H
+#define FRUSTUM_H
+
+class FRUSTUM {
+public:
+ float frustum[6][4];
+ void GetFrustum();
+ int CubeInFrustum(float, float, float, float);
+ int CubeInFrustum(float, float, float, float, float);
+ int SphereInFrustum(float, float, float, float);
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef _GAME_H_
+#define _GAME_H_
+
+#ifndef WIN32
+#include <Carbon.h>
+#include "Quicktime.h"
+#endif
+//Jordan included glut.h
+//#include <glut.h>
+
+#include "TGALoader.h"
+#ifdef WIN32
+#include "WinInput.h"
+#else
+#include "Macinput.h"
+#endif
+#include "Terrain.h"
+#include "Skybox.h"
+#include "Skeleton.h"
+#include "Models.h"
+#include "Lights.h"
+#include "Person.h"
+#include "Constants.h"
+#include "fmod.h"
+#include "Sprites.h"
+//#include <agl.h>
+#include "Text.h"
+#include "Objects.h"
+//#include <DrawSprocket.h>
+#include "Weapons.h"
+#include "binio.h"
+#include <fstream>
+#include "gl.h"
+
+extern GLuint rabbittexture;
+
+
+class Game
+{
+public:
+
+ typedef std::map<std::string, GLuint> TextureList;
+ typedef std::map<GLuint, std::string> GLTextureList;
+ typedef TextureList::iterator TexIter;
+ static TextureList textures;
+
+ GLuint terraintexture;
+ GLuint terraintexture2;
+ GLuint terraintexture3;
+ GLuint screentexture;
+ GLuint screentexture2;
+ GLuint logotexture;
+ GLuint loadscreentexture;
+ GLuint Maparrowtexture;
+ GLuint Mapboxtexture;
+ GLuint Mapcircletexture;
+ GLuint cursortexture;
+ GLuint Mainmenuitems[10];
+
+ int nummenuitems;
+ int startx[100];
+ int starty[100];
+ int endx[100];
+ int endy[100];
+ float selectedlong[100];
+ float offsetx[100];
+ float offsety[100];
+ float movex[100];
+ float movey[100];
+ float transition;
+ int anim;
+ int selected;
+ int loaddistrib;
+ int keyselect;
+ int indemo;
+ int registered;
+
+ bool won;
+
+ bool entername;
+
+ char menustring[100][256];
+ char registrationname[256];
+ float registrationnumber;
+
+ int newdetail;
+ int newscreenwidth;
+ int newscreenheight;
+
+ bool gameon;
+ float deltah,deltav;
+ int mousecoordh,mousecoordv;
+ int oldmousecoordh,oldmousecoordv;
+ float rotation,rotation2;
+ SkyBox skybox;
+ bool cameramode;
+ bool cameratogglekeydown;
+ bool chattogglekeydown;
+ int olddrawmode;
+ int drawmode;
+ bool drawmodetogglekeydown;
+ bool explodetogglekeydown;
+ bool detailtogglekeydown;
+ bool firstload;
+ bool oldbutton;
+
+ float leveltime;
+ float loadtime;
+
+ Model hawk;
+ XYZ hawkcoords;
+ XYZ realhawkcoords;
+ GLuint hawktexture;
+ float hawkrotation;
+ float hawkcalldelay;
+
+ Model eye;
+ Model iris;
+ Model cornea;
+
+ bool stealthloading;
+
+ int campaignnumlevels;
+ char campaignmapname[50][256];
+ char campaigndescription[50][256];
+ int campaignchoosenext[50];
+ int campaignnumnext[50];
+ int campaignnextlevel[50][10];
+ int campaignchoicesmade;
+ int campaignchoices[5000];
+ int campaignlocationx[50];
+ int campaignlocationy[50];
+ int campaignchoicenum;
+ int campaignchoicewhich[10];
+ int whichchoice;
+
+ int numlevelspassed;
+ int levelorder[5000];
+ int levelvisible[50];
+ int levelhighlight[50];
+
+ bool minimap;
+
+ int musictype,oldmusictype,oldoldmusictype;
+ bool realthreat;
+
+ Model rabbit;
+ XYZ rabbitcoords;
+
+ XYZ mapcenter;
+ float mapradius;
+
+ Text text;
+ float fps;
+
+ XYZ cameraloc;
+ float cameradist;
+
+ bool envtogglekeydown;
+ bool slomotogglekeydown;
+ bool texturesizetogglekeydown;
+ bool freezetogglekeydown;
+ int drawtoggle;
+
+ bool editorenabled;
+ int editortype;
+ float editorsize;
+ float editorrotation;
+ float editorrotation2;
+
+ float brightness;
+
+ int quit;
+ int tryquit;
+
+ XYZ pathpoint[30];
+ int numpathpoints;
+ int numpathpointconnect[30];
+ int pathpointconnect[30][30];
+ int pathpointselected;
+
+ int endgame;
+ bool scoreadded;
+ int numchallengelevels;
+
+ bool console;
+ int archiveselected;
+ char consoletext[15][256];
+ int consolechars[15];
+ bool chatting;
+ char displaytext[15][256];
+ int displaychars[15];
+ float displaytime[15];
+ float displayblinkdelay;
+ bool displayblink;
+ int displayselected;
+ bool consolekeydown;
+ bool consoletogglekeydown;
+ float consoleblinkdelay;
+ bool consoleblink;
+ int consoleselected;
+ int togglekey[140];
+ float togglekeydelay[140];
+ bool registernow;
+ bool autocam;
+
+ unsigned short crouchkey,jumpkey,forwardkey,chatkey,backkey,leftkey,rightkey,drawkey,throwkey,attackkey;
+ bool oldattackkey;
+
+ long long MD5_string (char *string);
+ static void LoadTexture(char *fileName, GLuint *textureid,int mipmap, bool hasalpha);
+ static void LoadTextureSave(char *fileName, GLuint *textureid,int mipmap,GLubyte *array, int *skinsize);
+ void LoadSave(char *fileName, GLuint *textureid,bool mipmap,GLubyte *array, int *skinsize);
+ bool AddClothes(char *fileName, GLuint *textureid,bool mipmap,GLubyte *array, int *skinsize);
+ void InitGame();
+ void LoadStuff();
+ void LoadingScreen();
+ void FadeLoadingScreen(float howmuch);
+ void Dispose();
+ int DrawGLScene(GLvoid);
+ void Tick();
+ void TickOnce();
+ void TickOnceAfter();
+ void SetUpLighting();
+ void Loadlevel(int which);
+ void Loadlevel(char *name);
+ void LoadSounds();
+ void Setenvironment(int which);
+ GLvoid ReSizeGLScene(float fov, float near);
+ int findPathDist(int start,int end);
+ int checkcollide(XYZ startpoint, XYZ endpoint);
+ int checkcollide(XYZ startpoint, XYZ endpoint, int what);
+ int loading;
+ float talkdelay;
+
+ int numboundaries;
+ XYZ boundary[360];
+
+ int whichlevel;
+ int oldenvironment;
+ int targetlevel;
+ float changedelay;
+
+ float musicvolume[4];
+ float oldmusicvolume[4];
+ int musicselected;
+ int change;
+ Game();
+ ~Game() {
+ for(int i=0;i<10;i++){
+ if(Mainmenuitems[i])glDeleteTextures( 1, (const unsigned long *)&Mainmenuitems[i] );
+ }
+ glDeleteTextures( 1, (const unsigned long *)&cursortexture );
+ glDeleteTextures( 1, (const unsigned long *)&Maparrowtexture );
+ glDeleteTextures( 1, (const unsigned long *)&Mapboxtexture );
+ glDeleteTextures( 1, (const unsigned long *)&Mapcircletexture );
+ glDeleteTextures( 1, (const unsigned long *)&terraintexture );
+ glDeleteTextures( 1, (const unsigned long *)&terraintexture2 );
+ if(screentexture>0)glDeleteTextures( 1, (const unsigned long *)&screentexture );
+ if(screentexture2>0)glDeleteTextures( 1, (const unsigned long *)&screentexture2 );
+ glDeleteTextures( 1, (const unsigned long *)&hawktexture );
+ glDeleteTextures( 1, (const unsigned long *)&logotexture );
+ glDeleteTextures( 1, (const unsigned long *)&loadscreentexture );
+
+ Dispose();
+ }
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "Game.h"
+
+using namespace std;
+
+extern XYZ viewer;
+extern int environment;
+extern float texscale;
+extern Light light;
+extern Terrain terrain;
+extern Sprites sprites;
+extern float multiplier;
+extern float sps;
+extern float viewdistance;
+extern float fadestart;
+extern float screenwidth,screenheight;
+#ifdef WIN32
+extern HDC hDC;
+#else
+extern AGLContext gaglContext;
+#endif
+extern int kTextureSize;
+extern FRUSTUM frustum;
+extern Light light;
+extern Objects objects;
+extern int detail;
+extern float usermousesensitivity;
+extern bool osx;
+extern float camerashake;
+extern Weapons weapons;
+extern Person player[maxplayers];
+extern int slomo;
+extern float slomodelay;
+extern bool ismotionblur;
+extern float woozy;
+extern float blackout;
+extern bool damageeffects;
+extern float volume;
+extern int numplayers;
+extern bool texttoggle;
+extern float blurness;
+extern float targetblurness;
+extern float playerdist;
+extern bool cellophane;
+extern bool freeze;
+extern float flashamount,flashr,flashg,flashb;
+extern int flashdelay;
+extern int netstate;
+extern float motionbluramount;
+extern bool isclient;
+extern bool alwaysblur;
+extern int test;
+extern bool tilt2weird;
+extern bool tiltweird;
+extern bool midweird;
+extern bool proportionweird;
+extern bool vertexweird[6];
+extern bool velocityblur;
+extern bool buttons[3];
+extern bool debugmode;
+extern int mainmenu;
+extern int oldmainmenu;
+extern int bloodtoggle;
+extern int difficulty;
+extern bool decals;
+// MODIFIED GWC
+//extern int texdetail;
+extern float texdetail;
+extern bool musictoggle;
+extern int bonus;
+extern float bonusvalue;
+extern float bonustotal;
+extern float bonustime;
+extern int oldbonus;
+extern float startbonustotal;
+extern float bonusnum[100];
+extern int tutoriallevel;
+extern float smoketex;
+extern float tutorialstagetime;
+extern float tutorialmaxtime;
+extern int tutorialstage;
+extern bool againbonus;
+extern float damagedealt;
+extern float damagetaken;
+extern bool invertmouse;
+
+extern int numhotspots;
+extern int winhotspot;
+extern int killhotspot;
+extern XYZ hotspot[40];
+extern int hotspottype[40];
+extern float hotspotsize[40];
+extern char hotspottext[40][256];
+extern int currenthotspot;
+
+extern int numaccounts;
+extern int accountactive;
+extern int accountdifficulty[10];
+extern int accountprogress[10];
+extern float accountpoints[10];
+extern float accounthighscore[10][50];
+extern float accountfasttime[10][50];
+extern bool accountunlocked[10][60];
+extern char accountname[10][256];
+
+extern int numfalls;
+extern int numflipfail;
+extern int numseen;
+extern int numstaffattack;
+extern int numswordattack;
+extern int numknifeattack;
+extern int numunarmedattack;
+extern int numescaped;
+extern int numflipped;
+extern int numwallflipped;
+extern int numthrowkill;
+extern int numafterkill;
+extern int numreversals;
+extern int numattacks;
+extern int maxalarmed;
+extern int numresponded;
+
+extern bool campaign;
+extern bool winfreeze;
+
+extern float menupulse;
+
+extern bool gamestart;
+
+extern int numdialogues;
+extern int numdialogueboxes[max_dialogues];
+extern int dialoguetype[max_dialogues];
+extern int dialogueboxlocation[max_dialogues][max_dialoguelength];
+extern float dialogueboxcolor[max_dialogues][max_dialoguelength][3];
+extern int dialogueboxsound[max_dialogues][max_dialoguelength];
+extern char dialoguetext[max_dialogues][max_dialoguelength][128];
+extern char dialoguename[max_dialogues][max_dialoguelength][64];
+extern XYZ dialoguecamera[max_dialogues][max_dialoguelength];
+extern XYZ participantlocation[max_dialogues][10];
+extern int participantfocus[max_dialogues][max_dialoguelength];
+extern int participantaction[max_dialogues][max_dialoguelength];
+extern float participantrotation[max_dialogues][10];
+extern XYZ participantfacing[max_dialogues][max_dialoguelength][10];
+extern float dialoguecamerarotation[max_dialogues][max_dialoguelength];
+extern float dialoguecamerarotation2[max_dialogues][max_dialoguelength];
+extern int indialogue;
+extern int whichdialogue;
+extern int directing;
+extern float dialoguetime;
+extern int dialoguegonethrough[20];
+
+extern int accountcampaignchoicesmade[10];
+extern int accountcampaignchoices[10][5000];
+
+extern float accountcampaignhighscore[10];
+extern float accountcampaignfasttime[10];
+extern float accountcampaignscore[10];
+extern float accountcampaigntime[10];
+
+extern bool gamestarted;
+
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+/*********************> DrawGLScene() <*****/
+long long Game::MD5_string (char *string){
+ char temp[256]="";
+ char temp2[256]="";
+ long long num=90814;
+
+ sprintf (temp, "%s",string);
+
+ int i=0;
+ while (i<256&&temp[i]!='\0'){
+ if(temp[i]%3==0)num+=temp[i]*124;
+ else if(temp[i]%3==1)num-=temp[i]*temp[i];
+ else num*=temp[i];
+ i++;
+ }
+
+ num=abs(num);
+ if(num==0)num+=1452;
+
+ while(num<5000000000000000){
+ num*=1.85421521;
+ }
+
+ while(num>9900000000000000){
+ num/=1.235421521;
+ }
+
+ return num;
+
+ //return 1111111111111111;
+}
+
+int Game::DrawGLScene(GLvoid)
+{
+ static float texcoordwidth,texcoordheight;
+ static float texviewwidth, texviewheight;
+ static int i,j,k,l;
+ static GLubyte color;
+ static float newbrightness;
+ static float changespeed;
+ static XYZ checkpoint;
+ static float tempmult;
+ float tutorialopac;
+ static char string[256]="";
+ static char string2[256]="";
+ static char string3[256]="";
+
+ static float lastcheck;
+
+ lastcheck+=multiplier;
+
+ glColorMask( 1.0, 1.0, 1.0, 1.0 );
+ if(!registered)debugmode=0;
+
+
+ if(freeze||winfreeze||(mainmenu&&gameon)||(!gameon&&gamestarted)){
+ tempmult=multiplier;
+ multiplier=0;
+ }
+
+ if(!mainmenu){
+ if(editorenabled){
+ numboundaries=mapradius*2;
+ if(numboundaries>360)numboundaries=360;
+ for(i=0;i<numboundaries;i++){
+ boundary[i]=0;
+ boundary[i].z=1;
+ boundary[i]=mapcenter+DoRotation(boundary[i]*mapradius,0,i*(360/((float)(numboundaries))),0);
+ }
+ }
+
+ SetUpLighting();
+
+ static int changed;
+ changed=0;
+
+ olddrawmode=drawmode;
+ if(ismotionblur&&!loading){
+ if((findLengthfast(&player[0].velocity)>200)&&velocityblur&&!cameramode){
+ drawmode=motionblurmode;
+ motionbluramount=200/(findLengthfast(&player[0].velocity));
+ changed=1;
+ }
+ if(player[0].damage-player[0].superpermanentdamage>(player[0].damagetolerance-player[0].superpermanentdamage)*1/2&&damageeffects&&!cameramode){
+ drawmode=doublevisionmode;
+ changed=1;
+ }
+ }
+
+ if(slomo&&!loading){
+ if(ismotionblur)
+ drawmode=motionblurmode;
+ motionbluramount=.2;
+ slomodelay-=multiplier;
+ if(slomodelay<0)slomo=0;
+ camerashake=0;
+ changed=1;
+ }
+ if((!changed&&!slomo)||loading){
+ drawmode=normalmode;
+ if(ismotionblur&&(/*fps>100||*/alwaysblur)){
+ if(olddrawmode!=realmotionblurmode)change=1;
+ else change=0;
+ drawmode=realmotionblurmode;
+ }
+ else if(olddrawmode==realmotionblurmode)change=2;
+ else change=0;
+ }
+
+ if(freeze||winfreeze||(mainmenu&&gameon)||(!gameon&&gamestarted))drawmode=normalmode;
+ if((freeze||winfreeze)&&ismotionblur&&!mainmenu)drawmode=radialzoommode;
+
+ if(winfreeze||mainmenu)drawmode=normalmode;
+
+ //drawmode=glowmode;
+ if(drawmode==glowmode){
+ RGBColor color2;
+ color2.red=0;
+ color2.green=0;
+ color2.blue=0;
+#ifndef WIN32
+ DSpContext_FadeGamma(NULL,200,&color2);
+#endif
+ }
+
+ if(drawtoggle!=2)drawtoggle=1-drawtoggle;
+
+ if(!texcoordwidth){
+
+ texviewwidth=kTextureSize;
+ if(texviewwidth>screenwidth)texviewwidth=screenwidth;
+ texviewheight=kTextureSize;
+ if(texviewheight>screenheight)texviewheight=screenheight;
+
+ texcoordwidth=screenwidth/kTextureSize;
+ texcoordheight=screenheight/kTextureSize;
+ if(texcoordwidth>1)texcoordwidth=1;
+ if(texcoordheight>1)texcoordheight=1;
+ }
+
+ glDrawBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
+
+ /*if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, (float)(abs(Random()%100))/50 );
+ else glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0);
+ */
+ if(abs(blurness-targetblurness)<multiplier*10||abs(blurness-targetblurness)>2){
+ blurness=targetblurness;
+ targetblurness=(float)(abs(Random()%100))/40;
+ }
+ if(blurness<targetblurness)blurness+=multiplier*5;
+ if(blurness>targetblurness)blurness-=multiplier*5;
+
+ //glFinish();
+ static XYZ terrainlight;
+ static float distance;
+ //if(drawmode==normalmode)ReSizeGLScene(90,.1);
+ if(drawmode==normalmode)ReSizeGLScene(90,.1f);
+ if(drawmode!=normalmode)glViewport(0,0,texviewwidth,texviewheight);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(1);
+ glAlphaFunc(GL_GREATER, 0.0001f);
+ glEnable(GL_ALPHA_TEST);
+ glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glMatrixMode (GL_MODELVIEW);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glLoadIdentity ();
+ if(!cameramode&&!freeze&&!winfreeze){
+ glRotatef(float(Random()%100)/10*camerashake/*+(woozy*woozy)/10*/,0,0,1);
+ glRotatef(rotation2+sin(woozy/2)*(player[0].damage/player[0].damagetolerance)*5,1,0,0);
+ glRotatef(rotation+sin(woozy)*(player[0].damage/player[0].damagetolerance)*5,0,1,0);
+ }
+ if(cameramode||freeze||winfreeze){
+ //glRotatef(float(Random()%100)/10*camerashake/*+(woozy*woozy)/10*/,0,0,1);
+ glRotatef(rotation2,1,0,0);
+ glRotatef(rotation,0,1,0);
+ }
+
+ if(environment==desertenvironment){
+ glRotatef((float)(abs(Random()%100))/3000-1,1,0,0);
+ glRotatef((float)(abs(Random()%100))/3000-1,0,1,0);
+ //glRotatef(blurness/40-1,1,0,0);
+ //glRotatef(blurness/40-1,0,1,0);
+ }
+ SetUpLight(&light,0);
+ glPushMatrix();
+ if(environment==desertenvironment&&detail==2)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness+.4 );
+ if(environment==desertenvironment){
+ glRotatef((float)(abs(Random()%100))/1000,1,0,0);
+ glRotatef((float)(abs(Random()%100))/1000,0,1,0);
+ }
+ skybox.draw();
+ glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0);
+ glPopMatrix();
+ glTranslatef(-viewer.x,-viewer.y,-viewer.z);
+ frustum.GetFrustum();
+
+ //Make Shadow
+ static XYZ point;
+ static float size,opacity,rotation;
+ rotation=0;
+ for(k=0;k<numplayers;k++){
+ if(!player[k].skeleton.free&&player[k].playerdetail&&player[k].howactive<typesleeping)
+ if(frustum.SphereInFrustum(player[k].coords.x,player[k].coords.y+player[k].scale*3,player[k].coords.z,player[k].scale*7)&&player[k].occluded<25)
+ for(i=0;i<player[k].skeleton.num_joints;i++){
+ if(player[k].skeleton.joints[i].label==leftknee||player[k].skeleton.joints[i].label==rightknee||player[k].skeleton.joints[i].label==groin){
+ point=DoRotation(player[k].skeleton.joints[i].position,0,player[k].rotation,0)*player[k].scale+player[k].coords;
+ size=.4f;
+ opacity=.4-player[k].skeleton.joints[i].position.y*player[k].scale/5-(player[k].coords.y-terrain.getHeight(player[k].coords.x,player[k].coords.z))/10;
+ if(k!=0&&tutoriallevel==1){
+ opacity=.2+.2*sin(smoketex*6+i)-player[k].skeleton.joints[i].position.y*player[k].scale/5-(player[k].coords.y-terrain.getHeight(player[k].coords.x,player[k].coords.z))/10;
+ }
+ terrain.MakeDecal(shadowdecal,point,size,opacity,rotation);
+ if(terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz])
+ for(l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ j=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ if(objects.position[j].y<player[k].coords.y||objects.type[j]==tunneltype||objects.type[j]==weirdtype){
+ point=DoRotation(DoRotation(player[k].skeleton.joints[i].position,0,player[k].rotation,0)*player[k].scale+player[k].coords-objects.position[j],0,-objects.rotation[j],0);
+ size=.4f;
+ opacity=.4f;
+ if(k!=0&&tutoriallevel==1){
+ opacity=.2+.2*sin(smoketex*6+i);
+ }
+ objects.model[j].MakeDecal(shadowdecal,&point,&size,&opacity,&rotation);
+ }
+ }
+ }
+ }
+ if((player[k].skeleton.free||player[k].howactive>=typesleeping)&&player[k].playerdetail)
+ if(frustum.SphereInFrustum(player[k].coords.x,player[k].coords.y,player[k].coords.z,player[k].scale*5)&&player[k].occluded<25)
+ for(i=0;i<player[k].skeleton.num_joints;i++){
+ if(player[k].skeleton.joints[i].label==leftknee||player[k].skeleton.joints[i].label==rightknee||player[k].skeleton.joints[i].label==groin||player[k].skeleton.joints[i].label==leftelbow||player[k].skeleton.joints[i].label==rightelbow||player[k].skeleton.joints[i].label==neck){
+ if(player[k].skeleton.free)point=player[k].skeleton.joints[i].position*player[k].scale+player[k].coords;
+ else point=DoRotation(player[k].skeleton.joints[i].position,0,player[k].rotation,0)*player[k].scale+player[k].coords;
+ size=.4f;
+ opacity=.4-player[k].skeleton.joints[i].position.y*player[k].scale/5-(player[k].coords.y-terrain.getHeight(player[k].coords.x,player[k].coords.z))/5;
+ if(k!=0&&tutoriallevel==1){
+ opacity=.2+.2*sin(smoketex*6+i)-player[k].skeleton.joints[i].position.y*player[k].scale/5-(player[k].coords.y-terrain.getHeight(player[k].coords.x,player[k].coords.z))/10;
+ }
+ terrain.MakeDecal(shadowdecal,point,size,opacity*.7,rotation);
+ if(terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz])
+ for(l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ j=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ if(objects.position[j].y<player[k].coords.y||objects.type[j]==tunneltype||objects.type[j]==weirdtype){
+ if(player[k].skeleton.free)point=DoRotation(player[k].skeleton.joints[i].position*player[k].scale+player[k].coords-objects.position[j],0,-objects.rotation[j],0);
+ else point=DoRotation(DoRotation(player[k].skeleton.joints[i].position,0,player[k].rotation,0)*player[k].scale+player[k].coords-objects.position[j],0,-objects.rotation[j],0);
+ size=.4f;
+ opacity=.4f;
+ if(k!=0&&tutoriallevel==1){
+ opacity=.2+.2*sin(smoketex*6+i);
+ }
+ objects.model[j].MakeDecal(shadowdecal,&point,&size,&opacity,&rotation);
+ }
+ }
+ }
+ }
+
+ if(!player[k].playerdetail)
+ if(frustum.SphereInFrustum(player[k].coords.x,player[k].coords.y,player[k].coords.z,player[k].scale*5))
+ {
+ point=player[k].coords;
+ size=.7;
+ opacity=.4-(player[k].coords.y-terrain.getHeight(player[k].coords.x,player[k].coords.z))/5;
+ terrain.MakeDecal(shadowdecal,point,size,opacity*.7,rotation);
+ if(terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz])
+ for(l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ j=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ point=DoRotation(player[k].coords-objects.position[j],0,-objects.rotation[j],0);
+ size=.7;
+ opacity=.4f;
+ objects.model[j].MakeDecal(shadowdecal,&point,&size,&opacity,&rotation);
+ }
+ }
+ }
+
+ //Terrain
+ glEnable(GL_TEXTURE_2D);
+ glDepthMask(1);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glBindTexture( GL_TEXTURE_2D, terraintexture);
+ terrain.draw(0);
+ glBindTexture( GL_TEXTURE_2D, terraintexture2);
+ terrain.draw(1);
+ //glBindTexture( GL_TEXTURE_2D, terraintexture3);
+ //glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ //terrain.draw(2);
+
+ terrain.drawdecals();
+
+ //Model
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glDisable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glDepthMask(1);
+
+ glEnable(GL_COLOR_MATERIAL);
+
+ test=2;
+ tilt2weird=0;
+ tiltweird=0;
+ midweird=0;
+ proportionweird=0;
+ vertexweird[0]=0;
+ vertexweird[1]=0;
+ vertexweird[2]=0;
+ vertexweird[3]=0;
+ vertexweird[4]=0;
+ vertexweird[5]=0;
+
+ if(!cellophane){
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ glDepthMask(1);
+ for(k=0;k<numplayers;k++){
+ if(k==0||tutoriallevel!=1){
+ glEnable(GL_BLEND);
+ glEnable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(player[k].coords.x,player[k].coords.z);
+ distance=findDistancefast(&viewer,&player[k].coords);
+ distance=(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance;
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ if(distance>=1)glDisable(GL_BLEND);
+ if(distance>=.5){
+ checkpoint=DoRotation(player[k].skeleton.joints[abs(Random()%player[k].skeleton.num_joints)].position,0,player[k].rotation,0)*player[k].scale+player[k].coords;
+ checkpoint.y+=1;
+ if(!player[k].occluded==0)i=checkcollide(viewer,checkpoint,player[k].lastoccluded);
+ if(i==-1||player[k].occluded==0)i=checkcollide(viewer,checkpoint);
+ if(i!=-1){
+ player[k].occluded+=1;
+ player[k].lastoccluded=i;
+ }
+ else player[k].occluded=0;
+ if(player[k].occluded<25)player[k].DrawSkeleton();
+ }
+ }
+ }
+ }
+
+ if(!cameramode&&musictype==stream_music2)playerdist=findDistancefastflat(&player[0].coords,&viewer);
+ else playerdist=-100;
+ glPushMatrix();
+ glCullFace(GL_BACK);
+ glEnable(GL_TEXTURE_2D);
+ objects.Draw();
+ glPopMatrix();
+
+ glPushMatrix();
+ if(frustum.SphereInFrustum(realhawkcoords.x+hawk.boundingspherecenter.x,realhawkcoords.y+hawk.boundingspherecenter.y,realhawkcoords.z+hawk.boundingspherecenter.z,2)){
+ glAlphaFunc(GL_GREATER, 0.0001f);
+ glDepthMask(1);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glTranslatef(hawkcoords.x,hawkcoords.y,hawkcoords.z);
+ glRotatef(hawkrotation,0,1,0);
+ glTranslatef(25,0,0);
+ distance=findDistancefast(&viewer,&realhawkcoords)*1.2;
+ glColor4f(light.color[0],light.color[1],light.color[2],(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance);
+ if((viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance>1)glColor4f(light.color[0],light.color[1],light.color[2],1);
+ if((viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance>0)
+ hawk.drawdifftex(hawktexture);
+ }
+ glPopMatrix();
+
+ //if(cellophane){
+ /*glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ glDepthMask(1);
+ for(k=0;k<numplayers;k++){
+ glEnable(GL_BLEND);
+ glEnable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(player[k].coords.x,player[k].coords.z);
+ distance=findDistancefast(&viewer,&player[k].coords);
+ distance=(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance;
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ if(distance>=1)glDisable(GL_BLEND);
+ if(distance>0){
+ checkpoint=DoRotation(player[k].skeleton.joints[abs(Random()%player[k].skeleton.num_joints)].position,0,player[k].rotation,0)*player[k].scale+player[k].coords;
+ checkpoint.y+=1;
+ if(checkcollide(viewer,checkpoint)){
+ player[k].occluded+=1;
+ }
+ else player[k].occluded=0;
+ if(player[k].occluded<25)player[k].DrawSkeleton();
+ }
+ }*/
+
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ glDepthMask(1);
+ for(k=0;k<numplayers;k++){
+ if(!(k==0||tutoriallevel!=1)){
+ glEnable(GL_BLEND);
+ glEnable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(player[k].coords.x,player[k].coords.z);
+ distance=findDistancefast(&viewer,&player[k].coords);
+ distance=(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance;
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ if(distance>=1)glDisable(GL_BLEND);
+ if(distance>=.5){
+ checkpoint=DoRotation(player[k].skeleton.joints[abs(Random()%player[k].skeleton.num_joints)].position,0,player[k].rotation,0)*player[k].scale+player[k].coords;
+ checkpoint.y+=1;
+ if(!player[k].occluded==0)i=checkcollide(viewer,checkpoint,player[k].lastoccluded);
+ if(i==-1||player[k].occluded==0)i=checkcollide(viewer,checkpoint);
+ if(i!=-1){
+ player[k].occluded+=1;
+ player[k].lastoccluded=i;
+ }
+ else player[k].occluded=0;
+ if(player[k].occluded<25)player[k].DrawSkeleton();
+ }
+ }
+ }
+ //}
+
+ glPushMatrix();
+ glEnable(GL_TEXTURE_2D);
+ weapons.Draw();
+ glPopMatrix();
+ glCullFace(GL_BACK);
+
+ glDisable(GL_COLOR_MATERIAL);
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+
+ glDepthMask(0);
+
+ sprites.Draw();
+
+ if(editorenabled){
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_COLOR_MATERIAL);
+ glColor4f(1,1,0,1);
+
+ for(k=0;k<numplayers;k++){
+ if(player[k].numwaypoints>1){
+ glBegin(GL_LINE_LOOP);
+ for(i=0;i<player[k].numwaypoints;i++){
+ glVertex3f(player[k].waypoints[i].x,player[k].waypoints[i].y+.5,player[k].waypoints[i].z);
+ }
+ glEnd();
+ }
+ }
+
+
+ if(numpathpoints>1){
+ glColor4f(0,1,0,1);
+ for(k=0;k<numpathpoints;k++){
+ if(numpathpointconnect[k]){
+ for(i=0;i<numpathpointconnect[k];i++){
+ glBegin(GL_LINE_LOOP);
+ glVertex3f(pathpoint[k].x,pathpoint[k].y+.5,pathpoint[k].z);
+ glVertex3f(pathpoint[pathpointconnect[k][i]].x,pathpoint[pathpointconnect[k][i]].y+.5,pathpoint[pathpointconnect[k][i]].z);
+ glEnd();
+ }
+ }
+ }
+ glColor4f(1,1,1,1);
+ glPointSize(4);
+ glBegin(GL_POINTS);
+ glVertex3f(pathpoint[pathpointselected].x,pathpoint[pathpointselected].y+.5,pathpoint[pathpointselected].z);
+ glEnd();
+ }
+ }
+
+ //Text
+
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(.5,.5,.5,1);
+ if(!console){
+ sprintf (string, " ",(int)(fps));
+ text.glPrint(10,30,string,0,.8,screenwidth,screenheight);
+
+ if(!tutoriallevel)
+ if(bonus>0&&bonustime<1&&!winfreeze&&indialogue==-1/*bonustime<4*/){
+ if(bonus==tracheotomy)sprintf (string, "Tracheotomy!");
+ else if(bonus==backstab)sprintf (string, "Backstabber!");
+ else if(bonus==spinecrusher)sprintf (string, "Spinecrusher!");
+ else if(bonus==ninja)sprintf (string, "Ninja Bonus!");
+ else if(bonus==style)sprintf (string, "Style Bonus!");
+ else if(bonus==cannon)sprintf (string, "Leg Cannon!");
+ else if(bonus==aimbonus)sprintf (string, "Nice Aim!");
+ else if(bonus==deepimpact)sprintf (string, "Heavy Impact!");
+ else if(bonus==touchofdeath)sprintf (string, "Touch of Death!");
+ else if(bonus==swordreversebonus)sprintf (string, "Sword Disarm!");
+ else if(bonus==staffreversebonus)sprintf (string, "Staff Disarm!");
+ else if(bonus==reverseko)sprintf (string, "Reversal KO!");
+ else if(bonus==solidhit)sprintf (string, "Solid Hit!");
+ else if(bonus==twoxcombo)sprintf (string, "2X Combo!");
+ else if(bonus==threexcombo)sprintf (string, "3X Combo!");
+ else if(bonus==fourxcombo)sprintf (string, "4X COMBO!");
+ else if(bonus==megacombo)sprintf (string, "MEGA COMBO!");
+ else if(bonus==Reversal)sprintf (string, "Reversal!");
+ else if(bonus==Stabbonus)sprintf (string, "Punctured!");
+ else if(bonus==Slicebonus)sprintf (string, "Sliced!");
+ else if(bonus==Bullseyebonus)sprintf (string, "Bullseye!");
+ else if(bonus==Slashbonus)sprintf (string, "Slashed!");
+ else if(bonus==Wolfbonus)sprintf (string, "WOLF SLAYER!");
+ else if(bonus==FinishedBonus)sprintf (string, "SLAIN!");
+ else if(bonus==TackleBonus)sprintf (string, "Tackle!");
+ else if(bonus==AboveBonus)sprintf (string, "Death from Above!");
+ else sprintf (string, "Excellent!");
+
+ glColor4f(0,0,0,1-bonustime);
+ text.glPrintOutline(1024/2-10*strlen(string)-4,768/16-4+768*4/5,string,1,2.5,1024,768);
+ glColor4f(1,0,0,1-bonustime);
+ text.glPrint(1024/2-10*strlen(string),768/16+768*4/5,string,1,2,1024,768);
+
+ sprintf (string, "%d",(int)bonusvalue);
+ glColor4f(0,0,0,1-bonustime);
+ text.glPrintOutline(1024/2-10*strlen(string)-4,768/16-4-20+768*4/5,string,1,2.5*.8,1024,768);
+ glColor4f(1,0,0,1-bonustime);
+ text.glPrint(1024/2-10*strlen(string),768/16-20+768*4/5,string,1,2*.8,1024,768);
+ glColor4f(.5,.5,.5,1);
+ }
+
+ if(tutoriallevel==1){
+ tutorialopac=tutorialmaxtime-tutorialstagetime;
+ if(tutorialopac>1)tutorialopac=1;
+ if(tutorialopac<0)tutorialopac=0;
+
+ sprintf (string, " ");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ if(tutorialstage==0){
+ sprintf (string, " ");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==1){
+ sprintf (string, "Welcome to the Lugaru training level!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==2){
+ sprintf (string, "BASIC MOVEMENT:");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==3){
+ sprintf (string, "You can move the mouse to rotate the camera.");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==4){
+ sprintf (string, "Try using the %s, %s, %s and %s keys to move around.",KeyToChar(forwardkey),KeyToChar(leftkey),KeyToChar(backkey),KeyToChar(rightkey));
+ sprintf (string2, "All movement is relative to the camera.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==5){
+ sprintf (string, "Please press %s to jump.",KeyToChar(jumpkey));
+ sprintf (string2, "You can hold it longer to jump higher.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==6){
+ sprintf (string, "You can press %s to crouch.",KeyToChar(crouchkey));
+ sprintf (string2, "You can jump higher from a crouching position.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==7){
+ sprintf (string, "While running, you can press %s to roll.",KeyToChar(crouchkey));
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==8){
+ sprintf (string, "While crouching, you can sneak around silently");
+ sprintf (string2, "using the movement keys.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==9){
+ sprintf (string, "Release the crouch key while sneaking and hold the movement keys");
+ sprintf (string2, "to run animal-style.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==10){
+ sprintf (string, "ADVANCED MOVEMENT:");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==11){
+ sprintf (string, "When you jump at a wall, you can hold %s again",KeyToChar(jumpkey));
+ sprintf (string2, "during impact to perform a walljump.");
+ sprintf (string3, "Be sure to use the movement keys to press against the wall");
+ }
+ if(tutorialstage==12){
+ sprintf (string, "While in the air, you can press crouch to flip.",KeyToChar(jumpkey));
+ sprintf (string2, "Walljumps and flips confuse enemies and give you more control.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==13){
+ sprintf (string, "BASIC COMBAT:");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==14){
+ sprintf (string, "There is now an imaginary enemy");
+ sprintf (string2, "in the middle of the training area.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==15){
+ if(attackkey==MAC_MOUSEBUTTON1)sprintf (string, "Click to attack when you are near an enemy.");
+ else sprintf (string, "Press %s to attack when you are near an enemy.",KeyToChar(attackkey));
+ sprintf (string2, "You can punch by standing still near an enemy and attacking.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==16){
+ sprintf (string, "If you are close, you will perform a weak punch.");
+ sprintf (string2, "The weak punch is excellent for starting attack combinations.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==17){
+ sprintf (string, "Attacking while running results in a spin kick.");
+ sprintf (string2, "This is one of your most powerful ground attacks.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==18){
+ sprintf (string, "Sweep the enemy's legs out by attacking while crouched.");
+ sprintf (string2, "This is a very fast attack, and easy to follow up.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==19){
+ sprintf (string, "When an enemy is on the ground, you can deal some extra");
+ sprintf (string2, "damage by running up and drop-kicking him.");
+ sprintf (string3, "(Try knocking them down with a sweep first)");
+ }
+ if(tutorialstage==20){
+ sprintf (string, "Your most powerful individual attack is the rabbit kick.");
+ if(attackkey==MAC_MOUSEBUTTON1)sprintf (string2, "Run at the enemy while holding the mouse button, and press");
+ else sprintf (string2, "Run at the enemy while holding %s, and press", KeyToChar(attackkey));
+ sprintf (string3, "the jump key (%s) to attack.",KeyToChar(jumpkey));
+ }
+ if(tutorialstage==21){
+ sprintf (string, "This attack is devastating if timed correctly.");
+ sprintf (string2, "Even if timed incorrectly, it will knock the enemy over.");
+ if(againbonus)sprintf (string3, "Try rabbit-kicking the imaginary enemy again.");
+ else sprintf (string3, "Try rabbit-kicking the imaginary enemy.");
+ }
+ if(tutorialstage==22){
+ sprintf (string, "If you sneak behind an enemy unnoticed, you can kill");
+ sprintf (string2, "him instantly. Move close behind this enemy");
+ sprintf (string3, "and attack.");
+ }
+ if(tutorialstage==23){
+ sprintf (string, "Another important attack is the wall kick. When an enemy");
+ sprintf (string2, "is near a wall, perform a walljump nearby and hold");
+ sprintf (string3, "the attack key during impact with the wall.");
+ }
+ if(tutorialstage==24){
+ sprintf (string, "You can tackle enemies by running at them animal-style");
+ if(attackkey==MAC_MOUSEBUTTON1)sprintf (string2, "and pressing jump (%s) or attack(mouse button).",KeyToChar(jumpkey));
+ else sprintf (string2, "and pressing jump (%s) or attack(%s).",KeyToChar(jumpkey),KeyToChar(attackkey));
+ sprintf (string3, "This is especially useful when they are running away.");
+ }
+ if(tutorialstage==25){
+ sprintf (string, "Dodge by pressing back and attack. Dodging is essential");
+ sprintf (string2, "against enemies with swords or other long weapons.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==26){
+ sprintf (string, "REVERSALS AND COUNTER-REVERSALS");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==27){
+ sprintf (string, "The enemy can now reverse your attacks.");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==28){
+ sprintf (string, "If you attack, you will notice that the enemy now sometimes");
+ sprintf (string2, "catches your attack and uses it against you. Hold");
+ sprintf (string3, "crouch (%s) after attacking to escape from reversals.",KeyToChar(crouchkey));
+ }
+ if(tutorialstage==29){
+ sprintf (string, "Try escaping from two more reversals in a row.");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==30){
+ sprintf (string, "Good!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==31){
+ sprintf (string, "To reverse an attack, you must tap crouch (%s) during the",KeyToChar(crouchkey));
+ sprintf (string2, "enemy's attack. You must also be close to the enemy;");
+ sprintf (string3, "this is especially important against armed opponents.");
+ }
+ if(tutorialstage==32){
+ sprintf (string, "The enemy can attack in %d seconds.", (int)(tutorialmaxtime-tutorialstagetime));
+ sprintf (string2, "This imaginary opponents attacks will be highlighted");
+ sprintf (string3, "to make this easier.");
+ }
+ if(tutorialstage==33){
+ sprintf (string, "Reverse three enemy attacks!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==34){
+ sprintf (string, "Reverse two more enemy attacks!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==35){
+ sprintf (string, "Reverse one more enemy attack!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==36){
+ sprintf (string, "Excellent!");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==37){
+ sprintf (string, "Now spar with the enemy for %d more seconds.", (int)(tutorialmaxtime-tutorialstagetime));
+ sprintf (string2, "Damage dealt: %d",(int)damagedealt);
+ sprintf (string3, "Damage taken: %d.",(int)damagetaken);
+ }
+ if(tutorialstage==38){
+ sprintf (string, "WEAPONS:");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==39){
+ sprintf (string, "There is now an imaginary knife");
+ sprintf (string2, "in the center of the training area.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==40){
+ sprintf (string, "Stand, roll or handspring over the knife");
+ sprintf (string2, "while pressing %s to pick it up.",KeyToChar(throwkey));
+ sprintf (string3, "You can crouch and press the same key to drop it again.");
+ }
+ if(tutorialstage==41){
+ sprintf (string, "You can equip and unequip weapons using the %s key.",KeyToChar(drawkey));
+ sprintf (string2, "Sometimes it is best to keep them unequipped to");
+ sprintf (string3, "prevent enemies from taking them. ");
+ }
+ if(tutorialstage==42){
+ sprintf (string, "The knife is the smallest weapon and the least encumbering.");
+ sprintf (string2, "You can equip or unequip it while standing, crouching,");
+ sprintf (string3, "running or flipping.");
+ }
+ if(tutorialstage==43){
+ sprintf (string, "You perform weapon attacks the same way as unarmed attacks,");
+ sprintf (string2, "but sharp weapons cause permanent damage, instead of the");
+ sprintf (string3, "temporary trauma from blunt weapons, fists and feet.");
+ }
+ if(tutorialstage==44){
+ sprintf (string, "The enemy now has your knife!");
+ sprintf (string2, "Please reverse two of his knife attacks.");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==45){
+ sprintf (string, "Please reverse one more of his knife attacks.");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==46){
+ sprintf (string, "Now he has a sword!");
+ sprintf (string2, "The sword has longer reach than your arms, so you");
+ sprintf (string3, "must move close to reverse the sword slash.");
+ }
+ if(tutorialstage==47){
+ sprintf (string, "Long weapons like the sword and staff are also useful for defense;");
+ sprintf (string2, "you can parry enemy weapon attacks by pressing the attack key");
+ sprintf (string3, "at the right time. Please try parrying the enemy's attacks!");
+ }
+ if(tutorialstage==48){
+ sprintf (string, "The staff is like the sword, but has two main attacks.");
+ sprintf (string2, "The standing smash is fast and effective, and the running");
+ sprintf (string3, "spin smash is slower and more powerful.");
+ }
+ if(tutorialstage==49){
+ sprintf (string, "When facing an enemy, you can throw the knife with %s.",KeyToChar(throwkey));
+ sprintf (string2, "It is possible to throw the knife while flipping,");
+ sprintf (string3, "but it is very inaccurate.");
+ }
+ if(tutorialstage==50){
+ sprintf (string, "You now know everything you can learn from training.");
+ sprintf (string2, "Everything else you must learn from experience!");
+ sprintf (string3, " ");
+ }
+ if(tutorialstage==51){
+ sprintf (string, "Walk out of the training area to return to the main menu.");
+ sprintf (string2, " ");
+ sprintf (string3, " ");
+ }
+
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string)*screenwidth/1024-4,screenheight/16-4+screenheight*4/5,string,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string2)*screenwidth/1024-4,screenheight/16-4+screenheight*4/5-20*screenwidth/1024,string2,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string3)*screenwidth/1024-4,screenheight/16-4+screenheight*4/5-40*screenwidth/1024,string3,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight);
+ glColor4f(1,1,1,tutorialopac);
+ text.glPrint(screenwidth/2-7.6*strlen(string)*screenwidth/1024,screenheight/16+screenheight*4/5,string,1,1.5*screenwidth/1024,screenwidth,screenheight);
+ text.glPrint(screenwidth/2-7.6*strlen(string2)*screenwidth/1024,screenheight/16+screenheight*4/5-20*screenwidth/1024,string2,1,1.5*screenwidth/1024,screenwidth,screenheight);
+ text.glPrint(screenwidth/2-7.6*strlen(string3)*screenwidth/1024,screenheight/16+screenheight*4/5-40*screenwidth/1024,string3,1,1.5*screenwidth/1024,screenwidth,screenheight);
+
+ sprintf (string, "Press 'tab' to skip to the next item.",KeyToChar(jumpkey));
+ sprintf (string2, "Press escape at any time to");
+ sprintf (string3, "pause or exit the tutorial.");
+
+ glColor4f(0,0,0,1);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string)*screenwidth/1024*.8-4,0-4+screenheight*1/10,string,1,1.5*1.25*screenwidth/1024*.8,screenwidth,screenheight);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string2)*screenwidth/1024*.8-4,0-4+screenheight*1/10-20*.8*screenwidth/1024,string2,1,1.5*1.25*screenwidth/1024*.8,screenwidth,screenheight);
+ text.glPrintOutline(screenwidth/2-7.6*strlen(string3)*screenwidth/1024*.8-4,0-4+screenheight*1/10-40*.8*screenwidth/1024,string3,1,1.5*1.25*screenwidth/1024*.8,screenwidth,screenheight);
+ glColor4f(0.5,0.5,0.5,1);
+ text.glPrint(screenwidth/2-7.6*strlen(string)*screenwidth/1024*.8,0+screenheight*1/10,string,1,1.5*screenwidth/1024*.8,screenwidth,screenheight);
+ text.glPrint(screenwidth/2-7.6*strlen(string2)*screenwidth/1024*.8,0+screenheight*1/10-20*.8*screenwidth/1024,string2,1,1.5*screenwidth/1024*.8,screenwidth,screenheight);
+ text.glPrint(screenwidth/2-7.6*strlen(string3)*screenwidth/1024*.8,0+screenheight*1/10-40*.8*screenwidth/1024,string3,1,1.5*screenwidth/1024*.8,screenwidth,screenheight);
+ }
+ //Hot spots
+
+ if(numhotspots&&(bonustime>=1||bonus<=0||bonustime<0)&&!tutoriallevel){
+ int closest=-1;
+ float closestdist=-1;
+ float distance=0;
+ closest=currenthotspot;
+ for(i=0;i<numhotspots;i++){
+ distance=findDistancefast(&player[0].coords,&hotspot[i]);
+ if(closestdist==-1||distance<closestdist){
+ if(findDistancefast(&player[0].coords,&hotspot[i])<hotspotsize[i]&&((hotspottype[i]<=10&&hotspottype[i]>=0)||(hotspottype[i]<=40&&hotspottype[i]>=20))){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ }
+ if(closest!=-1)
+ currenthotspot=closest;
+ if(currenthotspot!=-1){
+ if(hotspottype[closest]<=10){
+ if(findDistancefast(&player[0].coords,&hotspot[closest])<hotspotsize[closest])
+ tutorialstagetime=0;
+ tutorialmaxtime=1;
+ tutorialopac=tutorialmaxtime-tutorialstagetime;
+ if(tutorialopac>1)tutorialopac=1;
+ if(tutorialopac<0)tutorialopac=0;
+
+ sprintf (string, "%s", hotspottext[closest]);
+
+ int lastline;
+ int line=0;
+ bool done=0;
+ lastline=0;
+ i=0;
+ while(!done){
+ if(string[i]=='\n'||string[i]>'z'||string[i]<' '||string[i]=='\0'){
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrintOutline(screenwidth/2-7.6*(i-lastline)*screenwidth/1024-4,screenheight/16-4+screenheight*4/5-20*screenwidth/1024*line,string,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight,lastline,i);
+ glColor4f(1,1,1,tutorialopac);
+ text.glPrint(screenwidth/2-7.6*(i-lastline)*screenwidth/1024,screenheight/16+screenheight*4/5-20*screenwidth/1024*line,string,1,1.5*screenwidth/1024,screenwidth,screenheight,lastline,i);
+ lastline=i+1;
+ line++;
+ if(string[i]=='\0')done=1;
+ }
+ if(i>=255)done=1;
+ i++;
+ }
+ }
+ else if (hotspottype[closest]>=20&&dialoguegonethrough[hotspottype[closest]-20]==0){
+ whichdialogue=hotspottype[closest]-20;
+ for(j=0;j<numdialogueboxes[whichdialogue];j++){
+ player[participantfocus[whichdialogue][j]].coords=participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].rotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].targetrotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].velocity=0;
+ player[participantfocus[whichdialogue][j]].targetanimation=player[participantfocus[whichdialogue][j]].getIdle();
+ player[participantfocus[whichdialogue][j]].targetframe=0;
+ }
+ directing=0;
+ indialogue=0;
+ dialoguegonethrough[whichdialogue]++;
+ if(dialogueboxsound[whichdialogue][indialogue]!=0){
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=player[participantfocus[whichdialogue][indialogue]].coords.x;
+ gLoc[1]=player[participantfocus[whichdialogue][indialogue]].coords.y;
+ gLoc[2]=player[participantfocus[whichdialogue][indialogue]].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ int whichsoundplay;
+ if(dialogueboxsound[whichdialogue][indialogue]==1)whichsoundplay=rabbitchitter;
+ if(dialogueboxsound[whichdialogue][indialogue]==2)whichsoundplay=rabbitchitter2;
+ if(dialogueboxsound[whichdialogue][indialogue]==3)whichsoundplay=rabbitpainsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==4)whichsoundplay=rabbitpain1sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==5)whichsoundplay=rabbitattacksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==6)whichsoundplay=rabbitattack2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==7)whichsoundplay=rabbitattack3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==8)whichsoundplay=rabbitattack4sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==9)whichsoundplay=growlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==10)whichsoundplay=growl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==11)whichsoundplay=snarlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==12)whichsoundplay=snarl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==13)whichsoundplay=barksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==14)whichsoundplay=bark2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==15)whichsoundplay=bark3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==16)whichsoundplay=barkgrowlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-1)whichsoundplay=fireendsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-2)whichsoundplay=firestartsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-3)whichsoundplay=consolesuccesssound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-4)whichsoundplay=consolefailsound;
+ PlaySoundEx( whichsoundplay, samp[whichsoundplay], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsoundplay], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsoundplay], 256);
+ FSOUND_SetPaused(channels[whichsoundplay], FALSE);
+ }
+ }
+ }
+ }
+
+ if(indialogue!=-1&&!mainmenu){
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ if(dialogueboxlocation[whichdialogue][indialogue]==1)glTranslatef(0,screenheight*3/4,0);
+ glScalef(screenwidth,screenheight/4,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ glColor4f(dialogueboxcolor[whichdialogue][indialogue][0],dialogueboxcolor[whichdialogue][indialogue][1],dialogueboxcolor[whichdialogue][indialogue][2],0.7);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(1, 0, 0.0f);
+ glVertex3f(1, 1, 0.0f);
+ glVertex3f(0, 1, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ glEnable(GL_TEXTURE_2D);
+
+ tutorialopac=1;
+
+ float startx;
+ float starty;
+
+ startx=screenwidth*1/5;
+ if(dialogueboxlocation[whichdialogue][indialogue]==1)starty=screenheight/16+screenheight*4/5;
+ if(dialogueboxlocation[whichdialogue][indialogue]==2)starty=screenheight*1/5-screenheight/16;
+
+// char tempname[64];
+ char tempname[264];
+ bool goodchar;
+ int tempnum=0;
+// for(i=0;i<64;i++){
+ for(i=0;i<264;i++){
+ tempname[i]='\0';
+ }
+
+ for(i=0;i<(int)strlen(dialoguename[whichdialogue][indialogue]);i++){
+ tempname[tempnum]=dialoguename[whichdialogue][indialogue][i];
+ goodchar=1;
+ if(dialoguename[whichdialogue][indialogue][i]=='#'||dialoguename[whichdialogue][indialogue][i]=='\0')goodchar=0;
+ //if(tempnum>2)if(tempname[tempnum-2]=='e'&&tempname[tempnum-1]=='r')goodchar=0;
+ //if(tempnum>2)if(tempname[tempnum]=='r'&&tempname[0]=='a')goodchar=0;
+ if(goodchar)tempnum++;
+ else tempname[tempnum]='\0';
+ }
+
+ sprintf (string, "%s: ", tempname);
+
+ if(dialogueboxcolor[whichdialogue][indialogue][0]+dialogueboxcolor[whichdialogue][indialogue][1]+dialogueboxcolor[whichdialogue][indialogue][2]<1.5){
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrintOutline(startx-2*7.6*strlen(string)*screenwidth/1024-4,starty-4,string,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight);
+ glColor4f(0.7,0.7,0.7,tutorialopac);
+ text.glPrint(startx-2*7.6*strlen(string)*screenwidth/1024,starty,string,1,1.5*screenwidth/1024,screenwidth,screenheight);
+ }
+ else
+ {
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrintOutline(startx-2*7.6*strlen(string)*screenwidth/1024-4,starty-4,string,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight);
+
+ }
+
+ tempnum=0;
+ for(i=0;i<(int)strlen(dialoguetext[whichdialogue][indialogue])+1;i++){
+ tempname[tempnum]=dialoguetext[whichdialogue][indialogue][i];
+ if(dialoguetext[whichdialogue][indialogue][i]!='#')tempnum++;
+ }
+
+
+ sprintf (string, "%s", tempname);
+
+
+ int lastline;
+ int line=0;
+ bool done=0;
+ lastline=0;
+ i=0;
+ while(!done){
+ if(string[i]=='\n'||string[i]>'z'||string[i]<' '||string[i]=='\0'){
+ if(dialogueboxcolor[whichdialogue][indialogue][0]+dialogueboxcolor[whichdialogue][indialogue][1]+dialogueboxcolor[whichdialogue][indialogue][2]<1.5){
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrintOutline(startx/*-7.6*(i-lastline)*screenwidth/1024*/-4,starty-4-20*screenwidth/1024*line,string,1,1.5*1.25*screenwidth/1024,screenwidth,screenheight,lastline,i);
+ glColor4f(1,1,1,tutorialopac);
+ text.glPrint(startx/*-7.6*(i-lastline)*screenwidth/1024*/,starty-20*screenwidth/1024*line,string,1,1.5*screenwidth/1024,screenwidth,screenheight,lastline,i);
+ }
+ else
+ {
+ glColor4f(0,0,0,tutorialopac);
+ text.glPrint(startx/*-7.6*(i-lastline)*screenwidth/1024*/,starty-20*screenwidth/1024*line,string,1,1.5*screenwidth/1024,screenwidth,screenheight,lastline,i);
+ }
+ lastline=i+1;
+ line++;
+ if(string[i]=='\0')done=1;
+ }
+ if(i>=255)done=1;
+ i++;
+ }
+ }
+
+ if(!tutoriallevel&&!winfreeze&&indialogue==-1&&!mainmenu){
+ if(campaign){
+ if(!scoreadded)sprintf (string, "Score: %d", (int)accountcampaignscore[accountactive]+(int)bonustotal);//(int)bonustotal);
+ if(scoreadded)sprintf (string, "Score: %d", (int)accountcampaignscore[accountactive]);//(int)bonustotal);
+ }
+ if(!campaign)sprintf (string, "Score: %d", (int)bonustotal);
+ glColor4f(0,0,0,1);
+ text.glPrintOutline(1024/40-4,768/16-4+768*14/16,string,1,1.5*1.25,1024,768);
+ glColor4f(1,0,0,1);
+ text.glPrint(1024/40,768/16+768*14/16,string,1,1.5,1024,768);
+ }
+
+ glColor4f(.5,.5,.5,1);
+
+
+ if((texttoggle||editorenabled)&&debugmode&&!mainmenu){
+ sprintf (string, "The framespersecond is %d.",(int)(fps));
+ text.glPrint(10,30,string,0,.8,1024,768);
+
+ sprintf (string, "Name: %s", registrationname);
+ text.glPrint(10,260,string,0,.8,1024,768);
+
+
+ if(editorenabled)sprintf (string, "Map editor enabled.");
+ if(!editorenabled)sprintf (string, "Map editor Disabled.");
+ text.glPrint(10,60,string,0,.8,1024,768);
+ if(editorenabled){
+ sprintf (string, "Object size: %f",editorsize);
+ text.glPrint(10,75,string,0,.8,1024,768);
+ if(editorrotation>=0)sprintf (string, "Object rotation: %f",editorrotation);
+ else sprintf (string, "Object rotation: Random");
+ text.glPrint(10,90,string,0,.8,1024,768);
+ if(editorrotation2>=0)sprintf (string, "Object rotation2: %f",editorrotation2);
+ else sprintf (string, "Object rotation2: Random");
+ text.glPrint(10,105,string,0,.8,1024,768);
+ sprintf (string, "Object type: %d",editortype);
+ text.glPrint(10,120,string,0,.8,1024,768);
+ if(editortype==boxtype)sprintf (string, "(box)");
+ if(editortype==treetrunktype)sprintf (string, "(tree)");
+ if(editortype==walltype)sprintf (string, "(wall)");
+ if(editortype==weirdtype)sprintf (string, "(weird)");
+ if(editortype==spiketype)sprintf (string, "(spike)");
+ if(editortype==rocktype)sprintf (string, "(rock)");
+ if(editortype==bushtype)sprintf (string, "(bush)");
+ if(editortype==tunneltype)sprintf (string, "(tunnel)");
+ if(editortype==chimneytype)sprintf (string, "(chimney)");
+ if(editortype==platformtype)sprintf (string, "(platform)");
+ if(editortype==cooltype)sprintf (string, "(cool)");
+ if(editortype==firetype)sprintf (string, "(fire)");
+ text.glPrint(130,120,string,0,.8,1024,768);
+
+ sprintf (string, "Numplayers: %d",numplayers);
+ text.glPrint(10,155,string,0,.8,1024,768);
+ sprintf (string, "Player %d: numwaypoints: %d",numplayers,player[numplayers-1].numwaypoints);
+ text.glPrint(10,140,string,0,.8,1024,768);
+ }
+ /*sprintf (string, "Coords are: %f %f %f",player[0].coords.x,player[0].coords.y,player[0].coords.z);
+ text.glPrint(10,200,string,0,.8,1024,768);*/
+ sprintf (string, "Difficulty: %d",difficulty);
+ text.glPrint(10,240,string,0,.8,1024,768);
+ /*
+ sprintf (string, "lasthotspot: %d",hotspottype[numhotspots-1]);
+ text.glPrint(10,240,string,0,.8,1024,768);
+ sprintf (string, "killhotspot: %d",killhotspot);
+ text.glPrint(10,220,string,0,.8,1024,768);
+ sprintf (string, "winhotspot: %d",winhotspot);
+ text.glPrint(10,200,string,0,.8,1024,768);*/
+
+ }
+ }
+
+ if(drawmode==glowmode){
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(0,0,0,.5);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ if((((blackout&&damageeffects)||(player[0].bloodloss>0&&damageeffects&&player[0].blooddimamount>0)||player[0].dead)&&!cameramode)||console){
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ if(player[0].dead)blackout+=multiplier*3;
+ if(player[0].dead==1)blackout=.4f;
+ if(player[0].dead==2&&blackout>.6)blackout=.6;
+ glColor4f(0,0,0,blackout);
+ if(!player[0].dead){
+ if((player[0].bloodloss/player[0].damagetolerance*(sin(woozy)/4+.5))*.3<.3){
+ glColor4f(0,0,0,player[0].blooddimamount*player[0].bloodloss/player[0].damagetolerance*(sin(woozy)/4+.5)*.3);
+ blackout=player[0].blooddimamount*player[0].bloodloss/player[0].damagetolerance*(sin(woozy)/4+.5)*.3;
+ }
+ else {
+ glColor4f(0,0,0,player[0].blooddimamount*.3);
+ blackout=player[0].blooddimamount*.3;
+ }
+ }
+ if(console)glColor4f(.7,0,0,.2);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ if(flashamount>0&&damageeffects){
+ if(flashamount>1)flashamount=1;
+ if(flashdelay<=0)flashamount-=multiplier;
+ flashdelay--;
+ if(flashamount<0)flashamount=0;
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(flashr,flashg,flashb,flashamount);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ if(!console){
+ displaytime[0]=0;
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ if(chatting){
+ sprintf (string, " ]");
+ text.glPrint(10,30+screenheight-330,string,0,1,screenwidth,screenheight);
+ if(displayblink){
+ sprintf (string, "_");
+ text.glPrint(30+(float)(displayselected)*10,30+(screenheight-330),string,0,1,screenwidth,screenheight);
+ }
+ }
+ for(i=0;i<15;i++){
+ if((i!=0||chatting)&&displaytime[i]<4)
+ for(j=0;j<displaychars[i];j++){
+ glColor4f(1,1,1,4-displaytime[i]);
+ if(j<displaychars[i]){
+ sprintf (string, "%c",displaytext[i][j]);
+ text.glPrint(30+j*10,30+i*20+(screenheight-330),string,0,1,screenwidth,screenheight);
+ }
+ }
+ }
+ }
+
+ if(minimap&&indialogue==-1){
+ float mapviewdist;
+ mapviewdist=20000;
+
+ glDisable(GL_DEPTH_TEST);
+ glColor3f (1.0, 1.0, 1.0); // no coloring
+
+ glEnable(GL_TEXTURE_2D);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef((float)screenwidth/2,(float)screenwidth/2,1);
+ glTranslatef(1.75,.25,0);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(1,1,1,1);
+ glPushMatrix();
+ float opac;
+ opac=.7;
+ XYZ center;
+ float radius;
+ float distcheck;
+ center=0;
+ int numliveplayers=0;
+ for(i=0;i<numplayers;i++){
+ if(!player[i].dead)numliveplayers++;
+ }
+
+ int numadd;
+ numadd=0;
+
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==treetrunktype||objects.type[i]==boxtype){
+ center+=objects.position[i];
+ numadd++;
+ }
+ }
+ for(i=0;i<numplayers;i++){
+ if(!player[i].dead)center+=player[i].coords;
+ }
+ center/=numadd+numliveplayers;
+
+ center=player[0].coords;
+
+ float maxdistance=0;
+ float tempdist;
+ int whichclosest;
+ for(i=0;i<objects.numobjects;i++){
+ tempdist=findDistancefast(¢er,&objects.position[i]);
+ if(tempdist>maxdistance){
+ whichclosest=i;
+ maxdistance=tempdist;
+ }
+ }
+ for(i=0;i<numplayers;i++){
+ if(!player[i].dead){
+ tempdist=findDistancefast(¢er,&player[i].coords);
+ if(tempdist>maxdistance){
+ whichclosest=i;
+ maxdistance=tempdist;
+ }
+ }
+ }
+ radius=fast_sqrt(maxdistance);
+
+ radius=110;
+
+ glScalef(.25/radius*256*terrain.scale*.4,.25/radius*256*terrain.scale*.4,1);
+ glPushMatrix();
+ glScalef(1/(1/radius*256*terrain.scale*.4),1/(1/radius*256*terrain.scale*.4),1);
+ /*float startx,starty,endx,endy;
+ glBegin(GL_QUADS);
+ glTexCoord2f(1-(center.x-radius)/terrain.scale/256,(center.z-radius)/terrain.scale/256);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1-(center.x+radius)/terrain.scale/256,(center.z-radius)/terrain.scale/256);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1-(center.x+radius)/terrain.scale/256,(center.z+radius)/terrain.scale/256);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(1-(center.x-radius)/terrain.scale/256,(center.z+radius)/terrain.scale/256);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();*/
+ glPopMatrix();
+ glRotatef(player[0].lookrotation*-1+180,0,0,1);
+ glTranslatef(-(center.x/terrain.scale/256*-2+1),(center.z/terrain.scale/256*-2+1),0);
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==treetrunktype){
+ distcheck=findDistancefast(&player[0].coords,&objects.position[i]);
+ if(distcheck<mapviewdist){
+ glBindTexture( GL_TEXTURE_2D, Mapcircletexture);
+ glColor4f(0,.3,0,opac*(1-distcheck/mapviewdist));
+ glPushMatrix();
+ glTranslatef(objects.position[i].x/terrain.scale/256*-2+1,objects.position[i].z/terrain.scale/256*2-1,0);
+ glRotatef(objects.rotation[i],0,0,1);
+ glScalef(.003,.003,.003);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ if(objects.type[i]==boxtype){
+ distcheck=findDistancefast(&player[0].coords,&objects.position[i]);
+ if(distcheck<mapviewdist){
+ glBindTexture( GL_TEXTURE_2D, Mapboxtexture);
+ glColor4f(.4,.4,.4,opac*(1-distcheck/mapviewdist));
+ glPushMatrix();
+ glTranslatef(objects.position[i].x/terrain.scale/256*-2+1,objects.position[i].z/terrain.scale/256*2-1,0);
+ glRotatef(objects.rotation[i],0,0,1);
+ glScalef(.01*objects.scale[i],.01*objects.scale[i],.01*objects.scale[i]);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ }
+ if(editorenabled){
+ glBindTexture( GL_TEXTURE_2D, Mapcircletexture);
+ for(i=0;i<numboundaries;i++){
+ glColor4f(0,0,0,opac/3);
+ glPushMatrix();
+ glTranslatef(boundary[i].x/terrain.scale/256*-2+1,boundary[i].z/terrain.scale/256*2-1,0);
+ glScalef(.002,.002,.002);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ for(i=0;i<numplayers;i++){
+ distcheck=findDistancefast(&player[0].coords,&player[i].coords);
+ if(distcheck<mapviewdist){
+ glPushMatrix();
+ glBindTexture( GL_TEXTURE_2D, Maparrowtexture);
+ if(i==0)glColor4f(1,1,1,opac);
+ else if(player[i].dead==2||player[i].howactive>typesleeping)glColor4f(0,0,0,opac*(1-distcheck/mapviewdist));
+ else if(player[i].dead)glColor4f(.3,.3,.3,opac*(1-distcheck/mapviewdist));
+ else if(player[i].aitype==attacktypecutoff)glColor4f(1,0,0,opac*(1-distcheck/mapviewdist));
+ else if(player[i].aitype==passivetype)glColor4f(0,1,0,opac*(1-distcheck/mapviewdist));
+ else glColor4f(1,1,0,1);
+ glTranslatef(player[i].coords.x/terrain.scale/256*-2+1,player[i].coords.z/terrain.scale/256*2-1,0);
+ glRotatef(player[i].rotation+180,0,0,1);
+ glScalef(.005,.005,.005);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ /*glBegin(GL_TRIANGLES);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(0, 1, 0.0f);
+ glEnd();*/
+ glPopMatrix();
+ }
+ }
+ /*glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();*/
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ /*if(loading){
+ loading=2;
+ drawmode=normalmode;
+ }*/
+
+
+ if(loading&&!stealthloading&&(!campaign||player[0].dead)){
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(0,0,0,.7);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ //logo
+ glDisable(GL_DEPTH_TEST);
+ glColor3f (1.0, 1.0, 1.0); // no coloring
+
+ glEnable(GL_TEXTURE_2D);
+ /*glBindTexture( GL_TEXTURE_2D, logotexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef((float)screenwidth/2,(float)screenwidth/2,1);
+ glTranslatef(1.8,1.25,0);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(1,1,1,1);
+ glPushMatrix();
+ glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);*/
+
+ //Minimap
+
+ if(loading!=4){
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ sprintf (string, "Loading...");
+ text.glPrint(1024/2-90,768/2,string,1,2,1024,768);
+ }
+ loading=2;
+ //if(ismotionblur)drawmode=motionblurmode;
+ drawmode=normalmode;
+ }
+
+ if(winfreeze&&!campaign){
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(0,0,0,.4);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ //logo
+ glDisable(GL_DEPTH_TEST);
+ glColor3f (1.0, 1.0, 1.0); // no coloring
+
+ glEnable(GL_TEXTURE_2D);
+ /*glBindTexture( GL_TEXTURE_2D, logotexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef((float)screenwidth/2,(float)screenwidth/2,1);
+ glTranslatef(1.8,1.25,0);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(1,1,1,1);
+ glPushMatrix();
+ glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);*/
+
+ //Awards
+ int numawards;
+ int awards[30];
+ numawards=0;
+
+ if(damagetaken==0&&player[0].bloodloss==0){
+ awards[numawards]=awardflawless;
+ numawards++;
+ }
+ bool alldead;
+ alldead=1;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ if(player[i].dead!=2)alldead=0;
+ }
+ if(alldead){
+ awards[numawards]=awardalldead;
+ numawards++;
+ }
+ alldead=1;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ if(player[i].dead!=1)alldead=0;
+ }
+ if(alldead){
+ awards[numawards]=awardnodead;
+ numawards++;
+ }
+ if(numresponded==0&&!numthrowkill){
+ awards[numawards]=awardstealth;
+ numawards++;
+ }
+ if(numattacks==numstaffattack&&numattacks>0){
+ awards[numawards]=awardbojutsu;
+ numawards++;
+ }
+ if(numattacks==numswordattack&&numattacks>0){
+ awards[numawards]=awardswordsman;
+ numawards++;
+ }
+ if(numattacks==numknifeattack&&numattacks>0){
+ awards[numawards]=awardknifefighter;
+ numawards++;
+ }
+ if(numattacks==numunarmedattack&&numthrowkill==0&&weapons.numweapons>0){
+ awards[numawards]=awardkungfu;
+ numawards++;
+ }
+ if(numescaped>0){
+ awards[numawards]=awardevasion;
+ numawards++;
+ }
+ if(numflipfail==0&&numflipped+numwallflipped*2>20){
+ awards[numawards]=awardacrobat;
+ numawards++;
+ }
+ if(numthrowkill==numplayers-1){
+ awards[numawards]=awardlongrange;
+ numawards++;
+ }
+ alldead=1;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ if(player[i].dead!=2)alldead=0;
+ }
+ if(numafterkill>0&&alldead){
+ awards[numawards]=awardbrutal;
+ numawards++;
+ }
+ if(numreversals>((float)numattacks)*.8&&numreversals>3){
+ awards[numawards]=awardaikido;
+ numawards++;
+ }
+ if(maxalarmed==1&&numplayers>2){
+ awards[numawards]=awardstrategy;
+ numawards++;
+ }
+ if(numflipfail>3){
+ awards[numawards]=awardklutz;
+ numawards++;
+ }
+
+
+ //Win Screen Won Victory
+
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ sprintf (string, "Level Cleared!");
+ text.glPrintOutlined(1024/2-strlen(string)*10,768*7/8,string,1,2,1024,768);
+
+ sprintf (string, "Score: %d",(int)(bonustotal-startbonustotal));
+ text.glPrintOutlined(1024/30,768*6/8,string,1,2,1024,768);
+
+ if(!campaign)sprintf (string, "Press Escape to return to menu or Space to continue");
+ if(campaign)sprintf (string, "Press Escape or Space to continue");
+ text.glPrintOutlined(640/2-strlen(string)*5,480*1/16,string,1,1,640,480);
+
+ char temp[255];
+
+ for(i=0;i<255;i++)string[i]='\0';
+ sprintf (temp, "Time: %d:",(int)(((int)leveltime-(int)(leveltime)%60)/60));
+ strcat(string,temp);
+ if((int)(leveltime)%60<10)strcat(string,"0");
+ sprintf (temp, "%d",(int)(leveltime)%60);
+ strcat(string,temp);
+ text.glPrintOutlined(1024/30,768*6/8-40,string,1,2,1024,768);
+
+ for(i=0;i<numawards;i++){
+ if(i<6){
+ if(awards[i]==awardklutz)sprintf (string, "Suicidal");
+ if(awards[i]==awardflawless)sprintf (string, "Flawless!");
+ if(awards[i]==awardalldead)sprintf (string, "Take no prisoners");
+ if(awards[i]==awardnodead)sprintf (string, "Merciful");
+ if(awards[i]==awardstealth)sprintf (string, "One with the shadows!");
+ if(awards[i]==awardswordsman)sprintf (string, "Swordsman");
+ if(awards[i]==awardkungfu)sprintf (string, "Unarmed!");
+ if(awards[i]==awardknifefighter)sprintf (string, "Knife fighter");
+ if(awards[i]==awardcoward)sprintf (string, "Coward");
+ if(awards[i]==awardevasion)sprintf (string, "Escape artist");
+ if(awards[i]==awardacrobat)sprintf (string, "Gymnast");
+ if(awards[i]==awardlongrange)sprintf (string, "Blade slinger");
+ if(awards[i]==awardbrutal)sprintf (string, "Brutal");
+ if(awards[i]==awardhyper)sprintf (string, "Hyper");
+ if(awards[i]==awardaikido)sprintf (string, "Aikido master!");
+ if(awards[i]==awardrambo)sprintf (string, "Rambo");
+ if(awards[i]==awardfast)sprintf (string, "Fast");
+ if(awards[i]==awardrealfast)sprintf (string, "Real fast");
+ if(awards[i]==awarddamnfast)sprintf (string, "Damn fast");
+ if(awards[i]==awardstrategy)sprintf (string, "Divide and conquer");
+ if(awards[i]==awardbojutsu)sprintf (string, "Bojutsu");
+ text.glPrintOutlined(1024/30,768*6/8-90-40*i,string,1,2,1024,768);
+ }
+ }
+
+ //drawmode=normalmode;
+ }
+
+ if(drawmode!=normalmode){
+ glEnable(GL_TEXTURE_2D);
+ //glFinish();
+ if(!drawtoggle||drawmode!=realmotionblurmode||(drawtoggle==2||change==1)){
+ if(screentexture){
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
+ GLfloat subtractColor[4] = { 0.5, 0.5, 0.5, 0.0 };
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, subtractColor);
+ //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_SUBTRACT);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
+ glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
+
+ glBindTexture( GL_TEXTURE_2D, screentexture);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texviewwidth, texviewheight);
+ }
+ }
+ if((drawtoggle||change==1)&&drawmode==realmotionblurmode){
+ if(screentexture2){
+ glBindTexture( GL_TEXTURE_2D, screentexture2);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texviewwidth, texviewheight);
+ }
+ if(!screentexture2){
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ glGenTextures( 1, &screentexture2 );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, screentexture2);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTextureSize, kTextureSize, 0);
+ }
+ }
+ //glFlush();
+ }
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+ ReSizeGLScene(90,.1f);
+ glViewport(0,0,screenwidth,screenheight);
+
+ if(drawmode!=normalmode){
+ glDisable(GL_DEPTH_TEST);
+ if(drawmode==motionblurmode){
+ glDrawBuffer(GL_FRONT);
+ glReadBuffer(GL_BACK);
+ //myassert(glGetError() == GL_NO_ERROR);
+ //glFlush();
+ }
+ glColor3f (1.0, 1.0, 1.0); // no coloring
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, screentexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glTranslatef(1,1,0);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ if(drawmode==motionblurmode){
+ if(motionbluramount<.2)motionbluramount=.2;
+ //glColor4f(1,1,1,fast_sqrt(multiplier)*2.9*motionbluramount);
+ glColor4f(1,1,1,motionbluramount);
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ if(drawmode==realmotionblurmode){
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glBindTexture( GL_TEXTURE_2D, screentexture);
+ glColor4f(1,1,1,.5);
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glBindTexture( GL_TEXTURE_2D, screentexture2);
+ glColor4f(1,1,1,.5);
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ if(drawmode==doublevisionmode){
+ static float crosseyedness;
+ crosseyedness=abs(player[0].damage-player[0].superpermanentdamage-(player[0].damagetolerance-player[0].superpermanentdamage)*1/2)/30;
+ if(crosseyedness>1)crosseyedness=1;
+ if(crosseyedness<0)crosseyedness=0;
+ glColor4f(1,1,1,1);
+ glDisable(GL_BLEND);
+ glPushMatrix();
+ glScalef(1,1,1);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ if(crosseyedness){
+ glColor4f(1,1,1,.5);
+ glEnable(GL_BLEND);
+ glPushMatrix();
+ glTranslatef(.015*crosseyedness,0,0);
+ glScalef(1,1,1);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ if(drawmode==glowmode){
+ glColor4f(.5,.5,.5,.5);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glPushMatrix();
+ glTranslatef(.01,0,0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPushMatrix();
+ glTranslatef(-.01,0,0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPushMatrix();
+ glTranslatef(.0,.01,0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPushMatrix();
+ glTranslatef(0,-.01,0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ if(drawmode==radialzoommode){
+ for(i=0;i<3;i++){
+ //glRotatef((float)i*.1,0,0,1);
+ glColor4f(1,1,1,1/((float)i+1));
+ glPushMatrix();
+ glScalef(1+(float)i*.01,1+(float)i*.01,1);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(texcoordwidth,texcoordheight);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,texcoordheight);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ if(console){
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ if(console){
+ int offset;
+ offset=0;
+ if(consoleselected>=60)offset=consoleselected-60;
+ sprintf (string, " ]");
+ text.glPrint(10,30,string,0,1,1024,768);
+ if(consoleblink){
+ sprintf (string, "_");
+ text.glPrint(30+(float)(consoleselected)*10-offset*10,30,string,0,1,1024,768);
+ }
+ for(i=0;i<15;i++){
+ for(j=0;j<consolechars[i];j++){
+ glColor4f(1,1,1,1-(float)(i)/16);
+ if(j<consolechars[i]){
+ sprintf (string, "%c",consoletext[i][j]);
+ text.glPrint(30+j*10-offset*10,30+i*20,string,0,1,1024,768);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(freeze||winfreeze||(mainmenu&&gameon)||(!gameon&&gamestarted)||(mainmenu&&gameon)||(!gameon&&gamestarted)||(!gameon&&gamestarted)){
+ multiplier=tempmult;
+ }
+
+ if(mainmenu){
+ glDrawBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ ReSizeGLScene(90,.1f);
+
+ int temptexdetail;
+ temptexdetail=texdetail;
+ if(texdetail>2)texdetail=2;
+ if(mainmenu!=oldmainmenu&&oldmainmenu!=0){
+ if(mainmenu==1){
+ LoadTexture(":Data:Textures:Newgame.png",&Mainmenuitems[1],0,0);
+ LoadTexture(":Data:Textures:Quit.png",&Mainmenuitems[3],0,0);
+ /*if(oldmainmenu==1||oldmainmenu==0){
+ LoadTexture(":Data:Textures:World.png",&Mainmenuitems[7],0,0);
+ LoadTexture(":Data:Textures:Options.png",&Mainmenuitems[2],0,0);
+ LoadTexture(":Data:Textures:Lugaru.png",&Mainmenuitems[0],0,0);
+ loaddistrib=0;
+ }*/
+ }
+ if(mainmenu==2){
+ LoadTexture(":Data:Textures:Resume.png",&Mainmenuitems[1],0,0);
+ LoadTexture(":Data:Textures:Endgame.png",&Mainmenuitems[3],0,0);
+ /*if(oldmainmenu==2||oldmainmenu==0){
+ LoadTexture(":Data:Textures:World.png",&Mainmenuitems[7],0,0);
+ LoadTexture(":Data:Textures:Options.png",&Mainmenuitems[2],0,0);
+ LoadTexture(":Data:Textures:Lugaru.png",&Mainmenuitems[0],0,0);
+ loaddistrib=0;
+ }*/
+ }
+ }
+ if(lastcheck>.5||oldmainmenu!=mainmenu){
+ if(mainmenu==5){
+ // ifstream ipstream(":Data:Campaigns:main.txt");
+ ifstream ipstream("./Data/Campaigns/main.txt");
+ //campaignnumlevels=0;
+ //accountcampaignchoicesmade[accountactive]=0;
+ ipstream.ignore(256,':');
+ ipstream >> campaignnumlevels;
+ for(i=0;i<campaignnumlevels;i++){
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream >> campaignmapname[i];
+ ipstream.ignore(256,':');
+ ipstream >> campaigndescription[i];
+ for(j=0;j<256;j++){
+ if(campaigndescription[i][j]=='_')campaigndescription[i][j]=' ';
+ }
+ ipstream.ignore(256,':');
+ ipstream >> campaignchoosenext[i];
+ ipstream.ignore(256,':');
+ ipstream >> campaignnumnext[i];
+ if(campaignnumnext[i])
+ for(j=0;j<campaignnumnext[i];j++){
+ ipstream.ignore(256,':');
+ ipstream >> campaignnextlevel[i][j];
+ campaignnextlevel[i][j]-=1;
+ }
+ ipstream.ignore(256,':');
+ ipstream >> campaignlocationx[i];
+ //campaignlocationx[i]-=30;
+ ipstream.ignore(256,':');
+ ipstream >> campaignlocationy[i];
+ //campaignlocationy[i]+=30;
+ }
+ ipstream.close();
+
+ for(i=0;i<campaignnumlevels;i++){
+ levelvisible[i]=0;
+ levelhighlight[i]=0;
+ }
+
+ levelorder[0]=0;
+ levelvisible[0]=1;
+ if(accountcampaignchoicesmade[accountactive])
+ for(i=0;i<accountcampaignchoicesmade[accountactive];i++){
+ levelorder[i+1]=campaignnextlevel[levelorder[i]][accountcampaignchoices[accountactive][i]];
+ levelvisible[levelorder[i+1]]=1;
+ }
+ int whichlevelstart;
+ whichlevelstart=accountcampaignchoicesmade[accountactive]-1;
+ if(whichlevelstart<0){
+ accountcampaignscore[accountactive]=0;
+ accountcampaignfasttime[accountactive]=0;
+ campaignchoicenum=1;
+ campaignchoicewhich[0]=0;
+ }
+ else
+ {
+ campaignchoicenum=campaignnumnext[levelorder[whichlevelstart]];
+ if(campaignchoicenum==0){
+ if(accountcampaignscore[accountactive]>accountcampaignhighscore[accountactive])accountcampaignhighscore[accountactive]=accountcampaignscore[accountactive];
+ if(accountcampaignfasttime[accountactive]==0||accountcampaigntime[accountactive]<accountcampaignfasttime[accountactive])accountcampaignfasttime[accountactive]=accountcampaigntime[accountactive];
+ }
+ if(campaignchoicenum)
+ for(i=0;i<campaignchoicenum;i++){
+ campaignchoicewhich[i]=campaignnextlevel[levelorder[whichlevelstart]][i];
+ levelvisible[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ levelhighlight[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ }
+ }
+ /*levelorder[0]=0;
+ levelorder[1]=1;
+ levelorder[2]=2;
+ levelorder[3]=3;*/
+ }
+ }
+ if(mainmenu==5){
+ lastcheck=0;
+ }
+
+ texdetail=temptexdetail;
+
+ /*if(mainmenu!=0)*/oldmainmenu=mainmenu;
+
+ if(mainmenu==3||mainmenu==4||mainmenu==5||mainmenu==6||mainmenu==7||mainmenu==8||mainmenu==9||mainmenu==10||mainmenu==119||mainmenu==12||mainmenu==13||mainmenu==14||mainmenu==15||mainmenu==16||mainmenu==17){
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.001f);
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glPushMatrix();
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ glColor4f(0,0,0,1.0);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glDisable(GL_TEXTURE_2D);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glEnable(GL_BLEND);
+ glColor4f(0.4,0.4,0.4,1.0);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, Mainmenuitems[4]);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+
+ if(mainmenu==3){
+ nummenuitems=12;
+ if((float)newscreenwidth>(float)newscreenheight*1.61||(float)newscreenwidth<(float)newscreenheight*1.59)sprintf (menustring[0], "Resolution: %d*%d",(int)newscreenwidth,(int)newscreenheight);
+ else sprintf (menustring[0], "Resolution: %d*%d (widescreen)",(int)newscreenwidth,(int)newscreenheight);
+ startx[0]=10+20;
+ starty[0]=440;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ if(newdetail==2)sprintf (menustring[1], "Detail: High");
+ else if(newdetail==1)sprintf (menustring[1], "Detail: Medium");
+ else sprintf (menustring[1], "Detail: Low");
+ startx[1]=10+60;
+ starty[1]=405;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ if(bloodtoggle==2)sprintf (menustring[2], "Blood: On, high detail (slower)");
+ if(bloodtoggle==1)sprintf (menustring[2], "Blood: On, low detail");
+ if(bloodtoggle==0)sprintf (menustring[2], "Blood: Off");
+ startx[2]=10+70;
+ starty[2]=370;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ if(difficulty==2)sprintf (menustring[3], "Difficulty: Insane");
+ if(difficulty==1)sprintf (menustring[3], "Difficulty: Difficult");
+ if(difficulty==0)sprintf (menustring[3], "Difficulty: Easier");
+ startx[3]=10+20-1000;
+ starty[3]=335-1000;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ if(ismotionblur==1)sprintf (menustring[4], "Blur Effects: Enabled (less compatible)");
+ if(ismotionblur==0)sprintf (menustring[4], "Blur Effects: Disabled (more compatible)");
+ startx[4]=10;
+ starty[4]=335;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+
+ if(decals==1)sprintf (menustring[5], "Decals: Enabled (slower)");
+ if(decals==0)sprintf (menustring[5], "Decals: Disabled");
+ startx[5]=10+60;
+ starty[5]=300;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+
+ if(musictoggle==1)sprintf (menustring[6], "Music: Enabled");
+ if(musictoggle==0)sprintf (menustring[6], "Music: Disabled");
+ startx[6]=10+70;
+ starty[6]=265;
+ endx[6]=startx[6]+strlen(menustring[6])*10;
+ endy[6]=starty[6]+20;
+ movex[6]=0;
+ movey[6]=0;
+
+ if(invertmouse==1)sprintf (menustring[9], "Invert mouse: Yes");
+ if(invertmouse==0)sprintf (menustring[9], "Invert mouse: No");
+ startx[9]=10;
+ starty[9]=230;
+ endx[9]=startx[9]+strlen(menustring[9])*10;
+ endy[9]=starty[9]+20;
+ movex[9]=0;
+ movey[9]=0;
+
+ sprintf (menustring[10], "Mouse Speed: %d", (int)(usermousesensitivity*5));
+ startx[10]=20;
+ starty[10]=195;
+ endx[10]=startx[10]+strlen(menustring[10])*10;
+ endy[10]=starty[10]+20;
+ movex[10]=0;
+ movey[10]=0;
+
+ sprintf (menustring[11], "Volume: %d%", (int)(volume*100));
+ startx[11]=10+60;
+ starty[11]=155;
+ endx[11]=startx[11]+strlen(menustring[11])*10;
+ endy[11]=starty[11]+20;
+ movex[11]=0;
+ movey[11]=0;
+
+ sprintf (menustring[7], "-Configure Controls-");
+ startx[7]=10+15;
+ starty[7]=100;
+ endx[7]=startx[7]+strlen(menustring[7])*10;
+ endy[7]=starty[7]+20;
+ movex[7]=0;
+ movey[7]=0;
+
+ if(newdetail==detail&&newscreenheight==(int)screenheight&&newscreenwidth==(int)screenwidth)sprintf (menustring[8], "Back");
+ else sprintf (menustring[8], "Back (some changes take effect next time Lugaru is opened)");
+ startx[8]=10;
+ endx[8]=startx[8]+strlen(menustring[8])*10;
+ starty[8]=10;
+ endy[8]=starty[8]+20;
+ movex[8]=0;
+ movey[8]=0;
+ }
+
+ if(mainmenu==4){
+ nummenuitems=10;
+ if(keyselect!=0)sprintf (menustring[0], "Forwards: %s",KeyToChar(forwardkey));
+ else sprintf (menustring[0], "Forwards: _");
+ startx[0]=10;
+ starty[0]=400;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ if(keyselect!=1)sprintf (menustring[1], "Back: %s",KeyToChar(backkey));
+ else sprintf (menustring[1], "Back: _");
+ startx[1]=10+40;
+ starty[1]=360;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ if(keyselect!=2)sprintf (menustring[2], "Left: %s",KeyToChar(leftkey));
+ else sprintf (menustring[2], "Left: _");
+ startx[2]=10+40;
+ starty[2]=320;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ if(keyselect!=3)sprintf (menustring[3], "Right: %s",KeyToChar(rightkey));
+ else sprintf (menustring[3], "Right: _");
+ startx[3]=10+30;
+ starty[3]=280;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ if(keyselect!=4)sprintf (menustring[4], "Crouch: %s",KeyToChar(crouchkey));
+ else sprintf (menustring[4], "Crouch: _");
+ startx[4]=10+20;
+ starty[4]=240;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+
+ if(keyselect!=5)sprintf (menustring[5], "Jump: %s",KeyToChar(jumpkey));
+ else sprintf (menustring[5], "Jump: _");
+ startx[5]=10+40;
+ starty[5]=200;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+
+ if(keyselect!=6)sprintf (menustring[6], "Draw: %s",KeyToChar(drawkey));
+ else sprintf (menustring[6], "Draw: _");
+ startx[6]=10+40;
+ starty[6]=160;
+ endx[6]=startx[6]+strlen(menustring[6])*10;
+ endy[6]=starty[6]+20;
+ movex[6]=0;
+ movey[6]=0;
+
+ if(keyselect!=7)sprintf (menustring[7], "Throw: %s",KeyToChar(throwkey));
+ else sprintf (menustring[7], "Throw: _");
+ startx[7]=10+30;
+ starty[7]=120;
+ endx[7]=startx[7]+strlen(menustring[7])*10;
+ endy[7]=starty[7]+20;
+ movex[7]=0;
+ movey[7]=0;
+
+ if(keyselect!=8)sprintf (menustring[8], "Attack: %s",KeyToChar(attackkey));
+ else sprintf (menustring[8], "Attack: _");
+ startx[8]=10+20;
+ starty[8]=80;
+ endx[8]=startx[8]+strlen(menustring[8])*10;
+ endy[8]=starty[8]+20;
+ movex[8]=0;
+ movey[8]=0;
+
+
+
+ sprintf (menustring[9], "Back");
+ startx[9]=10;
+ endx[9]=startx[9]+strlen(menustring[9])*10;
+ starty[9]=10;
+ endy[9]=starty[9]+20;
+ movex[9]=0;
+ movey[9]=0;
+ }
+ if(mainmenu==5){
+ nummenuitems=7+accountcampaignchoicesmade[accountactive]+campaignchoicenum;
+
+ sprintf (menustring[0], "%s",accountname[accountactive]);
+ startx[0]=5;
+ starty[0]=400;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Tutorial");
+ startx[1]=5;
+ starty[1]=300;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "Challenge");
+ startx[2]=5;
+ starty[2]=240;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ sprintf (menustring[3], "Delete User");
+ startx[3]=400;
+ starty[3]=10;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ sprintf (menustring[4], "Main Menu");
+ startx[4]=5;
+ starty[4]=10;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+
+ sprintf (menustring[5], "Change User");
+ startx[5]=5;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ starty[5]=180;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+
+ //World
+
+ sprintf (menustring[6], "World");
+ startx[6]=30+120;
+ starty[6]=30+480-400-50;
+ endx[6]=startx[6]+400;
+ endy[6]=30+480-50;
+ movex[6]=0;
+ movey[6]=0;
+
+ if(accountcampaignchoicesmade[accountactive])
+ for(i=0;i<accountcampaignchoicesmade[accountactive];i++){
+ sprintf (menustring[7+i], campaigndescription[levelorder[i]]);
+ startx[7+i]=30+120+campaignlocationx[levelorder[i]]*400/512;
+ starty[7+i]=30+30+(512-campaignlocationy[levelorder[i]])*400/512;
+ endx[7+i]=startx[7+i]+10;
+ endy[7+i]=starty[7+i]+10;
+ movex[7+i]=0;
+ movey[7+i]=0;
+ }
+
+ if(campaignchoicenum>0)
+ for(i=accountcampaignchoicesmade[accountactive];i<accountcampaignchoicesmade[accountactive]+campaignchoicenum;i++){
+ sprintf (menustring[7+i], campaigndescription[levelorder[i]]);
+ startx[7+i]=30+120+campaignlocationx[campaignchoicewhich[i-(accountcampaignchoicesmade[accountactive])]]*400/512;
+ starty[7+i]=30+30+(512-campaignlocationy[campaignchoicewhich[i-(accountcampaignchoicesmade[accountactive])]])*400/512;
+ endx[7+i]=startx[7+i]+10;
+ endy[7+i]=starty[7+i]+10;
+ movex[7+i]=0;
+ movey[7+i]=0;
+ }
+
+ /*sprintf (menustring[7], "Dot");
+ startx[7]=120+260*400/512;
+ starty[7]=30+(512-184)*400/512;
+ endx[7]=startx[7]+10;
+ endy[7]=starty[7]+10;
+ movex[7]=0;
+ movey[7]=0;
+
+ sprintf (menustring[8], "Dot");
+ startx[8]=120+129*400/512;
+ starty[8]=30+(512-284)*400/512;
+ endx[8]=startx[8]+10;
+ endy[8]=starty[8]+10;
+ movex[8]=0;
+ movey[8]=0;
+
+ sprintf (menustring[9], "Dot");
+ startx[9]=120+358*400/512;
+ starty[9]=30+(512-235)*400/512;
+ endx[9]=startx[9]+10;
+ endy[9]=starty[9]+10;
+ movex[9]=0;
+ movey[9]=0;
+
+ sprintf (menustring[10], "Dot");
+ startx[10]=120+359*400/512;
+ starty[10]=30+(512-308)*400/512;
+ endx[10]=startx[10]+10;
+ endy[10]=starty[10]+10;
+ movex[10]=0;
+ movey[10]=0;
+
+ sprintf (menustring[11], "Dot");
+ startx[11]=120+288*400/512;
+ starty[11]=30+(512-277)*400/512;
+ endx[11]=startx[11]+10;
+ endy[11]=starty[11]+10;
+ movex[11]=0;
+ movey[11]=0;*/
+ }
+
+ if(mainmenu==6){
+ nummenuitems=3;
+
+ sprintf (menustring[0], "Are you sure you want to delete this user?");
+ startx[0]=10;
+ starty[0]=400;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Yes");
+ startx[1]=10;
+ starty[1]=360;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "No");
+ startx[2]=10;
+ starty[2]=320;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ sprintf (menustring[3], "Extra 4");
+ startx[3]=10;
+ starty[3]=280;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ sprintf (menustring[4], "Extra 5");
+ startx[4]=10;
+ starty[4]=240;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+
+ sprintf (menustring[5], "Back");
+ startx[5]=10;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ starty[5]=10;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+ }
+
+ if(mainmenu==7){
+ nummenuitems=numaccounts+2;
+
+ int num;
+
+ if(numaccounts<8)
+ sprintf (menustring[0], "New User");
+ else
+ sprintf (menustring[0], "No More Users");
+ startx[0]=10;
+ starty[0]=400;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ if(entername)startx[0]+=10;
+
+
+ num=1;
+ if(numaccounts)
+ for(i=0;i<numaccounts;i++){
+ sprintf (menustring[num], "%s",accountname[i]);
+ startx[num]=10;
+ starty[num]=360-20-20*num;
+ endx[num]=startx[num]+strlen(menustring[num])*10;
+ endy[num]=starty[num]+20;
+ movex[num]=0;
+ movey[num]=0;
+
+ num++;
+ }
+
+ sprintf (menustring[num], "Back");
+ startx[num]=10;
+ endx[num]=startx[num]+strlen(menustring[num])*10;
+ starty[num]=10;
+ endy[num]=starty[num]+20;
+ movex[num]=0;
+ movey[num]=0;
+ }
+ if(mainmenu==8){
+ nummenuitems=3;
+
+ sprintf (menustring[0], "Easier");
+ startx[0]=10;
+ starty[0]=400;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Difficult");
+ startx[1]=10;
+ starty[1]=360;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "Insane");
+ startx[2]=10;
+ starty[2]=320;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+ }
+ if(mainmenu==9){
+ int tempncl;
+ //tempncl=numchallengelevels;
+ //numchallengelevels=9;
+ nummenuitems=2+numchallengelevels;
+ char temp[255];
+
+ for(j=0;j<numchallengelevels;j++){
+ for(i=0;i<255;i++)menustring[j][i]='\0';
+ sprintf (temp, "Level %d",j+1);
+ strcpy(menustring[j],temp);
+ for(i=0;i<17;i++)if(menustring[j][i]=='\0')menustring[j][i]=' ';
+ menustring[j][17]='\0';
+ sprintf (temp, "%d",(int)accounthighscore[accountactive][j]);
+ strcat(menustring[j],temp);
+ for(i=18;i<32;i++)if(menustring[j][i]=='\0')menustring[j][i]=' ';
+ menustring[j][32]='\0';
+ sprintf (temp, "%d:",(int)(((int)accountfasttime[accountactive][j]-(int)(accountfasttime[accountactive][j])%60)/60));
+ strcat(menustring[j],temp);
+ if((int)(accountfasttime[accountactive][j])%60<10)strcat(menustring[j],"0");
+ sprintf (temp, "%d",(int)(accountfasttime[accountactive][j])%60);
+ strcat(menustring[j],temp);
+
+ startx[j]=10;
+ starty[j]=400-j*25;
+ endx[j]=startx[j]+strlen(menustring[j])*10;
+ endy[j]=starty[j]+20;
+ movex[j]=0;
+ movey[j]=0;
+ }
+
+ sprintf (menustring[numchallengelevels], "Back");
+ startx[numchallengelevels]=10;
+ endx[numchallengelevels]=startx[numchallengelevels]+strlen(menustring[numchallengelevels])*10;
+ starty[numchallengelevels]=10;
+ endy[numchallengelevels]=starty[numchallengelevels]+20;
+ movex[numchallengelevels]=0;
+ movey[numchallengelevels]=0;
+
+ sprintf (menustring[numchallengelevels+1], " High Score Best Time");
+ startx[numchallengelevels+1]=10;
+ starty[numchallengelevels+1]=440;
+ endx[numchallengelevels+1]=startx[numchallengelevels+1]+strlen(menustring[numchallengelevels+1])*10;
+ endy[numchallengelevels+1]=starty[numchallengelevels+1]+20;
+ movex[numchallengelevels+1]=0;
+ movey[numchallengelevels+1]=0;
+
+ //numchallengelevels=tempncl;
+
+ }
+ if(mainmenu==11){
+ nummenuitems=2+numchallengelevels;
+ char temp[255];
+
+ for(j=0;j<numchallengelevels;j++){
+ for(i=0;i<255;i++)menustring[j][i]='\0';
+ sprintf (temp, "Level %d",j+1);
+ strcpy(menustring[j],temp);
+ for(i=0;i<17;i++)if(menustring[j][i]=='\0')menustring[j][i]=' ';
+ menustring[j][17]='\0';
+ sprintf (temp, "%d",(int)accounthighscore[accountactive][j]);
+ strcat(menustring[j],temp);
+ for(i=18;i<32;i++)if(menustring[j][i]=='\0')menustring[j][i]=' ';
+ menustring[j][32]='\0';
+ sprintf (temp, "%d:",(int)(((int)accountfasttime[accountactive][j]-(int)(accountfasttime[accountactive][j])%60)/60));
+ strcat(menustring[j],temp);
+ if((int)(accountfasttime[accountactive][j])%60<10)strcat(menustring[j],"0");
+ sprintf (temp, "%d",(int)(accountfasttime[accountactive][j])%60);
+ strcat(menustring[j],temp);
+
+ startx[j]=10;
+ starty[j]=360-j*40;
+ endx[j]=startx[j]+strlen(menustring[j])*10;
+ endy[j]=starty[j]+20;
+ movex[j]=0;
+ movey[j]=0;
+ }
+
+ sprintf (menustring[numchallengelevels], "Back");
+ startx[numchallengelevels]=10;
+ endx[numchallengelevels]=startx[numchallengelevels]+strlen(menustring[numchallengelevels])*10;
+ starty[numchallengelevels]=10;
+ endy[numchallengelevels]=starty[numchallengelevels]+20;
+ movex[numchallengelevels]=0;
+ movey[numchallengelevels]=0;
+
+ sprintf (menustring[numchallengelevels+1], " High Score Best Time");
+ startx[numchallengelevels+1]=10;
+ starty[numchallengelevels+1]=400;
+ endx[numchallengelevels+1]=startx[numchallengelevels+1]+strlen(menustring[numchallengelevels+1])*10;
+ endy[numchallengelevels+1]=starty[numchallengelevels+1]+20;
+ movex[numchallengelevels+1]=0;
+ movey[numchallengelevels+1]=0;
+
+ }
+ if(mainmenu==10){
+ nummenuitems=6;
+ char temp[255];
+
+ sprintf (menustring[0], "Congratulations!");
+ startx[0]=220;
+ starty[0]=330;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "You have avenged your family and");
+ startx[1]=140;
+ starty[1]=300;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "restored peace to the island of Lugaru.");
+ startx[2]=110;
+ starty[2]=270;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ sprintf (menustring[3], "Back");
+ startx[3]=10;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ starty[3]=10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ for(i=0;i<255;i++)menustring[4][i]='\0';
+ sprintf (temp, "Your score:");
+ strcpy(menustring[4],temp);
+ for(i=0;i<20;i++)if(menustring[4][i]=='\0')menustring[4][i]=' ';
+ menustring[4][20]='\0';
+ sprintf (temp, "%d",(int)accountcampaignscore[accountactive]);
+ strcat(menustring[4],temp);
+ startx[4]=190;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ starty[4]=200;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+ /*
+ for(i=0;i<255;i++)menustring[5][i]='\0';
+ sprintf (temp, "Your time:");
+ strcpy(menustring[5],temp);
+ for(i=0;i<20;i++)if(menustring[5][i]=='\0')menustring[5][i]=' ';
+ menustring[5][20]='\0';
+ sprintf (temp, "%d",(int)accountcampaigntime[accountactive]);
+ strcat(menustring[5],temp);
+ startx[5]=200;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ starty[5]=180;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+ */
+ for(i=0;i<255;i++)menustring[5][i]='\0';
+ sprintf (temp, "Highest score:");
+ strcpy(menustring[5],temp);
+ for(i=0;i<20;i++)if(menustring[5][i]=='\0')menustring[5][i]=' ';
+ menustring[5][20]='\0';
+ sprintf (temp, "%d",(int)accountcampaignhighscore[accountactive]);
+ strcat(menustring[5],temp);
+ startx[5]=190;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ starty[5]=180;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+ /*
+ for(i=0;i<255;i++)menustring[7][i]='\0';
+ sprintf (temp, "Lowest time:");
+ strcpy(menustring[7],temp);
+ for(i=0;i<20;i++)if(menustring[7][i]=='\0')menustring[7][i]=' ';
+ menustring[7][20]='\0';
+ sprintf (temp, "%d",(int)accountcampaignfasttime[accountactive]);
+ strcat(menustring[7],temp);
+ startx[7]=200;
+ endx[7]=startx[7]+strlen(menustring[7])*10;
+ starty[7]=130;
+ endy[7]=starty[7]+20;
+ movex[7]=0;
+ movey[7]=0;*/
+ }
+ }
+
+ if(mainmenu==12){
+ menupulse+=multiplier*2;
+
+ nummenuitems=6;
+ char temp[255];
+
+ sprintf (menustring[0], "Register now for only $19.95!");
+ startx[0]=160;
+ starty[0]=270;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Confront raiders, wolves, and more!");
+ startx[1]=130;
+ starty[1]=240;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "Fight using swords, staves and armor!");
+ startx[2]=125;
+ starty[2]=210;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ if(!tryquit)sprintf (menustring[3], "Back");
+ else sprintf (menustring[3], "Quit");
+ startx[3]=10;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ starty[3]=10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ sprintf (menustring[4], "Register now!");
+ startx[4]=250;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ starty[4]=140;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+
+ sprintf (menustring[5], "Enter registration code!");
+ startx[5]=190;
+ endx[5]=startx[5]+strlen(menustring[5])*10;
+ starty[5]=120;
+ endy[5]=starty[5]+20;
+ movex[5]=0;
+ movey[5]=0;
+ }
+
+ if(mainmenu==15){
+ nummenuitems=2;
+ char temp[255];
+
+ sprintf (menustring[0], "Thank you for supporting Wolfire Software!");
+ startx[0]=100;
+ starty[0]=270;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Back");
+ startx[1]=10;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ starty[1]=10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+ }
+
+ if(mainmenu==16){
+ nummenuitems=5;
+ char temp[255];
+
+ sprintf (menustring[0], "Sorry, that name/serial number combination is incorrect.");
+ startx[0]=40;
+ starty[0]=270;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Back");
+ startx[1]=10;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ starty[1]=10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+
+ sprintf (menustring[2], "Please make sure you are copying your name and serial");
+ startx[2]=50;
+ starty[2]=240;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0;
+
+ sprintf (menustring[3], "number exactly as they appear in your email.");
+ startx[3]=90;
+ starty[3]=210;
+ endx[3]=startx[3]+strlen(menustring[3])*10;
+ endy[3]=starty[3]+20;
+ movex[3]=0;
+ movey[3]=0;
+
+ sprintf (menustring[4], "Capitalization and punctuation matter!");
+ startx[4]=120;
+ starty[4]=180;
+ endx[4]=startx[4]+strlen(menustring[4])*10;
+ endy[4]=starty[4]+20;
+ movex[4]=0;
+ movey[4]=0;
+ }
+
+ if(mainmenu==13){
+ nummenuitems=2;
+ char temp[255];
+
+ sprintf (menustring[0], "Please enter your name:");
+ startx[0]=50;
+ starty[0]=250;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Please enter your name:");
+ startx[1]=290;
+ starty[1]=250;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+ }
+
+ if(mainmenu==14){
+ nummenuitems=2;
+ char temp[255];
+
+ sprintf (menustring[0], "Please enter your number:");
+ startx[0]=30;
+ starty[0]=250;
+ endx[0]=startx[0]+strlen(menustring[0])*10;
+ endy[0]=starty[0]+20;
+ movex[0]=0;
+ movey[0]=0;
+
+ sprintf (menustring[1], "Please enter your name:");
+ startx[1]=290;
+ starty[1]=250;
+ endx[1]=startx[1]+strlen(menustring[1])*10;
+ endy[1]=starty[1]+20;
+ movex[1]=0;
+ movey[1]=0;
+ /*
+ char tempstring[256];
+ sprintf (tempstring, "%s", registrationname);
+ long num1;
+ long num2;
+ long num3;
+ long num4;
+ long long longnum;
+ longnum = MD5_string ( tempstring);
+ //longnum = 1111111111111111;
+ num1 = longnum/100000000;
+ num2 = longnum%100000000;
+ sprintf (tempstring, "%d-%d-%d-%d", num1/10000, num1%10000, num2/10000, num2%10000);
+
+ sprintf (menustring[2], "%s", tempstring);
+ startx[2]=290;
+ starty[2]=230;
+ endx[2]=startx[2]+strlen(menustring[2])*10;
+ endy[2]=starty[2]+20;
+ movex[2]=0;
+ movey[2]=0; */
+ }
+
+ if(mainmenu==1||mainmenu==2){
+ nummenuitems=7;
+ startx[0]=150;
+ starty[0]=480-128;
+ endx[0]=150+256;
+ endy[0]=480;
+ movex[0]=0;
+ movey[0]=0;
+
+ startx[1]=18;
+ starty[1]=480-152-32;
+ endx[1]=18+128;
+ endy[1]=480-152;
+ movex[1]=0;
+ movey[1]=0;
+
+ startx[2]=18;
+ starty[2]=480-228-32;
+ endx[2]=2+128;
+ endy[2]=480-228;
+ movex[2]=0;
+ movey[2]=0;
+
+ if(mainmenu==1){
+ startx[3]=18;
+ starty[3]=480-306-32;
+ endx[3]=22+64;
+ endy[3]=480-306;
+ movex[3]=0;
+ movey[3]=0;
+ }
+
+ if(mainmenu==2){
+ startx[3]=18;
+ starty[3]=480-306-32;
+ endx[3]=22+128;
+ endy[3]=480-306;
+ movex[3]=0;
+ movey[3]=0;
+ }
+
+ /*startx[4]=150;
+ starty[4]=480-256;
+ endx[4]=150+256;
+ endy[4]=480;
+ */
+ if(anim==0){
+ startx[4]=380;
+ starty[4]=480-140-256;
+ endx[4]=380+256;
+ endy[4]=480-140;
+ movex[4]=80;
+ movey[4]=0;
+
+ startx[5]=145;
+ starty[5]=480-138-256;
+ endx[5]=145+256;
+ endy[5]=480-138;
+ movex[5]=40;
+ movey[5]=0;
+
+ startx[6]=254;
+ starty[6]=480-144-256;
+ endx[6]=254+256;
+ endy[6]=480-144;
+ movex[6]=20;
+ movey[6]=0;
+ }
+ if(anim==1){
+ startx[4]=180;
+ starty[4]=480-140-256;
+ endx[4]=180+256;
+ endy[4]=480-140;
+ movex[4]=80;
+ movey[4]=0;
+
+ startx[5]=500;
+ starty[5]=480-138-256;
+ endx[5]=500+256;
+ endy[5]=480-138;
+ movex[5]=40;
+ movey[5]=0;
+
+ startx[6]=340;
+ starty[6]=480-144-256;
+ endx[6]=340+256;
+ endy[6]=480-144;
+ movex[6]=20;
+ movey[6]=0;
+ }
+ if(anim==2){
+ startx[4]=460;
+ starty[4]=480-140-256;
+ endx[4]=460+256;
+ endy[4]=480-140;
+ movex[4]=50;
+ movey[4]=0;
+
+ startx[5]=295;
+ starty[5]=480-150-256;
+ endx[5]=295+256;
+ endy[5]=480-138;
+ movex[5]=-10;
+ movey[5]=0;
+
+ startx[6]=204;
+ starty[6]=480-144-256;
+ endx[6]=204+256;
+ endy[6]=480-144;
+ movex[6]=-30;
+ movey[6]=0;
+ }
+ if(anim==3){
+ startx[4]=150;
+ starty[4]=480-140-256;
+ endx[4]=200+256;
+ endy[4]=480-140;
+ movex[4]=80;
+ movey[4]=0;
+
+ startx[5]=350;
+ starty[5]=480-150-256;
+ endx[5]=350+256;
+ endy[5]=480-138;
+ movex[5]=5;
+ movey[5]=0;
+
+ startx[6]=500;
+ starty[6]=480-144-256;
+ endx[6]=500+256;
+ endy[6]=480-144;
+ movex[6]=-10;
+ movey[6]=0;
+ }
+ if(anim==4){
+ startx[4]=190;
+ starty[4]=480-100-256;
+ endx[4]=190+256;
+ endy[4]=480-100;
+ movex[4]=-30;
+ movey[4]=0;
+
+ startx[5]=185;
+ starty[5]=480-120-256;
+ endx[5]=185+256;
+ endy[5]=480-120;
+ movex[5]=-5;
+ movey[5]=0;
+
+ startx[6]=400;
+ starty[6]=480-144-256;
+ endx[6]=400+256;
+ endy[6]=480-144;
+ movex[6]=20;
+ movey[6]=0;
+ }
+ }
+
+ selected=-1;
+
+ if(mainmenu==1||mainmenu==2)
+ for(i=1;i<4;i++){
+ if((mousecoordh/screenwidth*640)>startx[i]&&(mousecoordh/screenwidth*640)<endx[i]&&480-(mousecoordv/screenheight*480)>starty[i]&&480-(mousecoordv/screenheight*480)<endy[i]){
+ selected=i;
+ }
+ }
+
+ if(mainmenu==3||mainmenu==4||mainmenu==5||mainmenu==6||mainmenu==7||mainmenu==8||mainmenu==9||mainmenu==10||mainmenu==11||mainmenu==12||mainmenu==13||mainmenu==14||mainmenu==15||mainmenu==16||mainmenu==17)
+ for(i=0;i<nummenuitems;i++){
+ if((mousecoordh/screenwidth*640)>startx[i]&&(mousecoordh/screenwidth*640)<endx[i]&&480-(mousecoordv/screenheight*480)>starty[i]&&480-(mousecoordv/screenheight*480)<endy[i]){
+ if(mainmenu!=5)selected=i;
+ if(mainmenu==5&&(i!=0&&i!=6))selected=i;
+ if(mainmenu==9&&(i!=numchallengelevels+1))selected=i;
+ if(mainmenu==11&&(i!=numchallengelevels+1))selected=i;
+ }
+ }
+
+ if(nummenuitems>0)
+ for(i=0;i<nummenuitems;i++){
+ if(selected==i)selectedlong[i]+=multiplier*5;
+ if(selectedlong[i]>1)selectedlong[i]=1;
+ if(selected!=i)selectedlong[i]-=multiplier*5;
+ if(selectedlong[i]<0)selectedlong[i]=0;
+ //if(i>=4)selectedlong[i]=.3;
+ if(i>=4&&(mainmenu==1||mainmenu==2))selectedlong[i]=0;
+ }
+
+ if(nummenuitems>0)
+ for(i=0;i<nummenuitems;i++){
+ offsetx[i]=(startx[i]+endx[i])/2-(mousecoordh/screenwidth*640);
+ offsety[i]=(starty[i]+endy[i])/2-(480-(mousecoordv/screenheight*480));
+ offsetx[i]*=.06f;
+ offsety[i]*=.06f;
+ offsetx[i]=0;
+ offsety[i]=0;
+ if(i>=4&&(mainmenu==1||mainmenu==2)){
+ offsetx[i]=(startx[i]+endx[i]+movex[i]*transition)/2-(640+190)/2;
+ offsety[i]=(starty[i]+endy[i]+movey[i]*transition)/2-(336+150)/2;
+ offsetx[i]*=.06f;
+ offsety[i]*=.06f;
+ }
+ }
+
+ if(mainmenu==1||mainmenu==2){
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.001f);
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glPushMatrix();
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ glColor4f(0,0,0,1.0);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glDisable(GL_TEXTURE_2D);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glEnable(GL_BLEND);
+ glColor4f(0.4,0.4,0.4,1.0);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, Mainmenuitems[4]);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,640,0,480,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glPushMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(1,0,0,1);
+ /*glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ if(anim!=1)glVertex3f(190, 150, 0.0f);
+ if(anim==1)glVertex3f(190+movex[4]*transition, 150, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(640, 150, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(640, 336, 0.0f);
+ glTexCoord2f(0,1);
+ if(anim!=1)glVertex3f(190, 336, 0.0f);
+ if(anim==1)glVertex3f(190+movex[4]*transition, 336, 0.0f);
+ glEnd();
+ glPopMatrix();*/
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+
+ }
+
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,640,0,480,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glEnable(GL_TEXTURE_2D);
+ if(nummenuitems>0)
+ {
+ for(j=0;j<nummenuitems;j++)
+ {
+ if(j<=3||(mainmenu!=1&&mainmenu!=2))
+ {
+ //glDisable(GL_BLEND);
+ glEnable(GL_ALPHA_TEST);
+ glEnable(GL_BLEND);
+ //glDisable(GL_ALPHA_TEST);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ if(mainmenu==1||mainmenu==2)
+ {
+ glColor4f(1,1,1,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glBindTexture( GL_TEXTURE_2D, Mainmenuitems[j]);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(startx[j]+movex[j]*transition, starty[j]+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(endx[j]+movex[j]*transition, starty[j]+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(endx[j]+movex[j]*transition, endy[j]+movey[j]*transition, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(startx[j]+movex[j]*transition, endy[j]+movey[j]*transition, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glEnable(GL_BLEND);
+ //glDisable(GL_ALPHA_TEST);
+ if(j<4)glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ for(i=0;i<10;i++)
+ {
+ if(1-((float)i)/10-(1-selectedlong[j])>0)
+ {
+ glColor4f(1,1,1,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(startx[j]-((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, starty[j]-((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(endx[j]+((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, starty[j]-((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(endx[j]+((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, endy[j]+((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(startx[j]-((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, endy[j]+((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ }
+ if(mainmenu==3||mainmenu==4||mainmenu==5||mainmenu==6||mainmenu==7||mainmenu==8||mainmenu==9||mainmenu==10||mainmenu==11||mainmenu==12||mainmenu==13||mainmenu==14||mainmenu==15||mainmenu==16||mainmenu==17)
+ {
+ if(mainmenu!=5||j<6)
+ {
+ glColor4f(1,0,0,1);
+ if(mainmenu==12&&j==4)glColor4f(1,(sin(menupulse)+1)/2,(sin(menupulse)+1)/2,1);
+ if(mainmenu==9&&j>accountprogress[accountactive]&&j<numchallengelevels)glColor4f(0.5,0,0,1);
+ if(mainmenu==11&&j>accountprogress[accountactive]&&j<numchallengelevels)glColor4f(0.5,0,0,1);
+ //if(1-((float)i)/10-(1-selectedlong[j])>0){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if((mainmenu!=7||j!=0||!entername)&&(mainmenu!=13||j!=1)&&(mainmenu!=14||j!=1))text.glPrint(startx[j],starty[j],menustring[j],0,1,640,480);
+ else
+ {
+ if(displayblink){
+ sprintf (string, "_");
+ text.glPrint(startx[j]+(float)(displayselected)*10,starty[j],string,0,1,640,480);
+ }
+ k=0;
+ for(l=0;l<displaychars[k];l++){
+ if(l<displaychars[k]){
+ sprintf (string, "%c",displaytext[k][l]);
+ text.glPrint(startx[j]+l*10,starty[j],string,0,1,640,480);
+ }
+ }
+ }
+ glPopMatrix();
+ /*}
+ else{
+ glPushMatrix();
+ sprintf (string, "Hooo!");
+ text.glPrint(startx[0],starty[0],string,0,1,640,480);
+ glPopMatrix();
+ }*/
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ for(i=0;i<15;i++)
+ {
+ if(1-((float)i)/15-(1-selectedlong[j])>0)
+ {
+ glColor4f(1,0,0,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ if(mainmenu==12&&j==4)glColor4f(1,(sin(menupulse)+1)/2,(sin(menupulse)+1)/2,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ if(mainmenu==9&&j>accountprogress[accountactive]&&j<numchallengelevels)glColor4f(0.5,0,0,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ if(mainmenu==11&&j>accountprogress[accountactive]&&j<numchallengelevels)glColor4f(0.5,0,0,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ if(mainmenu==3)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4-((/*1*/+((float)i)/70)*strlen(menustring[j]))*3,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==4)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==5)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==6)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==7&&(j!=0||!entername))text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==8)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==9)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==11)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==10)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==12)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==15)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==16)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==17)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==13&&j!=1)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ if(mainmenu==14&&j!=1)text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4/*-((((float)i)/70)*strlen(menustring[j]))*3*/,starty[j]/*-i*1/2*/+offsety[j]*((float)i)/4,menustring[j],0,1+((float)i)/70,640,480);
+ /*else{
+ if(displayblink){
+ sprintf (string, "_");
+ text.glPrint(startx[j]-((float)i)+offsetx[j]*((float)i)/4+(float)(displayselected)*10*(1+((float)i)/70),starty[j]+offsety[j]*((float)i)/4,string,0,1+((float)i)/70,640,480);
+ }
+ k=0;
+ for(l=0;l<displaychars[k];l++){
+ if(l<displaychars[k]){
+ sprintf (string, "%c",displaytext[k][l]);
+ text.glPrint(startx[j]-((float)k)+offsetx[j]*((float)k)/4+l*10*(1+((float)i)/70),starty[j]+offsety[j]*((float)i)/4,string,0,1+((float)i)/70,640,480);
+ }
+ }
+ }*/
+ }
+ }
+ }
+ else
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.001f);
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ if(j==6)glColor4f(1,1,1,1);
+ else glColor4f(1,0,0,1);
+
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,640,0,480,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glPushMatrix();
+
+ //Draw world, draw map
+ glTranslatef(2,-5,0);
+
+ if(j>6&&j<nummenuitems-1)
+ {
+ XYZ linestart,lineend,offset;
+ XYZ fac;
+ float startsize;
+ float endsize;
+ linestart=0;
+ lineend=0;
+ offset=0;
+ //float linestartx,lineendx,linestarty,lineendy,offsetx,offsety;
+ linestart.x=(startx[j]+endx[j])/2;
+ linestart.y=(starty[j]+endy[j])/2;
+ if(j>=6+accountcampaignchoicesmade[accountactive]){
+ linestart.x=(startx[6+accountcampaignchoicesmade[accountactive]]+endx[6+accountcampaignchoicesmade[accountactive]])/2;
+ linestart.y=(starty[6+accountcampaignchoicesmade[accountactive]]+endy[6+accountcampaignchoicesmade[accountactive]])/2;
+ }
+ lineend.x=(startx[j+1]+endx[j+1])/2;
+ lineend.y=(starty[j+1]+endy[j+1])/2;
+ offset=lineend-linestart;
+ fac=offset;
+ Normalise(&fac);
+ offset=DoRotation(offset,0,0,90);
+ Normalise(&offset);
+ glDisable(GL_TEXTURE_2D);
+
+ if(j<6+accountcampaignchoicesmade[accountactive]){
+ glColor4f(0.5,0,0,1);
+ startsize=.5;
+ endsize=.5;
+ }
+ if(j>=6+accountcampaignchoicesmade[accountactive]){
+ glColor4f(1,0,0,1);
+ endsize=1;
+ startsize=.5;
+ }
+
+ linestart+=fac*4*startsize;
+ lineend-=fac*4*endsize;
+
+ if(!(j>7+accountcampaignchoicesmade[accountactive]+campaignchoicenum)){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(linestart.x-offset.x*startsize, linestart.y-offset.y*startsize, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(linestart.x+offset.x*startsize, linestart.y+offset.y*startsize, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(lineend.x+offset.x*endsize, lineend.y+offset.y*endsize, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(lineend.x-offset.x*endsize, lineend.y-offset.y*endsize, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ glEnable(GL_TEXTURE_2D);
+ }
+
+
+ if(j==6)glBindTexture( GL_TEXTURE_2D, Mainmenuitems[7]);
+ else glBindTexture( GL_TEXTURE_2D, Mapcircletexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ if(j-7<accountcampaignchoicesmade[accountactive])glColor4f(0.5,0,0,1);
+ if(j-7>=accountcampaignchoicesmade[accountactive])glColor4f(1,0,0,1);
+ if(j==6)glColor4f(1,1,1,1);
+ XYZ midpoint;
+ float itemsize;
+ itemsize=abs(startx[j]-endx[j])/2;
+ midpoint=0;
+ midpoint.x=(startx[j]+endx[j])/2;
+ midpoint.y=(starty[j]+endy[j])/2;
+ if(j>6&&(j-7<accountcampaignchoicesmade[accountactive]))itemsize*=.5;
+ if(!(j-7>accountcampaignchoicesmade[accountactive]+campaignchoicenum))
+ {
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(midpoint.x-itemsize+movex[j]*transition, midpoint.y-itemsize+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(midpoint.x+itemsize+movex[j]*transition, midpoint.y-itemsize+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(midpoint.x+itemsize+movex[j]*transition, midpoint.y+itemsize+movey[j]*transition, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(midpoint.x-itemsize+movex[j]*transition, midpoint.y+itemsize+movey[j]*transition, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glEnable(GL_BLEND);
+ //glDisable(GL_ALPHA_TEST);
+ if(j<4)glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ for(i=0;i<10;i++)
+ {
+ if(1-((float)i)/10-(1-selectedlong[j])>0)
+ {
+ glColor4f(1,0,0,(1-((float)i)/10-(1-selectedlong[j]))*.25);
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(midpoint.x-itemsize-((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, midpoint.y-itemsize-((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(midpoint.x+itemsize+((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, midpoint.y-itemsize-((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(midpoint.x+itemsize+((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, midpoint.y+itemsize+((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(midpoint.x-itemsize-((float)i)*1/2+offsetx[j]*((float)i)/2+movex[j]*transition, midpoint.y+itemsize+((float)i)*1/2+offsety[j]*((float)i)/2+movey[j]*transition, 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ }
+ }
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+
+ if(j-7>=accountcampaignchoicesmade[accountactive]){
+ //glColor4f(0,0,0,1);
+ //text.glPrintOutline(startx[j]+10-1.5,starty[j]-4-1.5,menustring[j],0,0.6*1.25,640,480);
+ //glColor4f(1,0,0,1);
+ //text.glPrint(startx[j]+10,starty[j]-4,menustring[j],0,0.6,640,480);
+ text.glPrintOutlined(0.9,0,0,startx[j]+10,starty[j]-4,menustring[j],0,0.6,640,480);
+ glDisable(GL_DEPTH_TEST);
+ }
+ }
+ }
+ }
+ }
+ }
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix();
+
+ if(mainmenu==1||mainmenu==2)
+ if(transition<.1||transition>.9){
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.001f);
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,640,0,480,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glPushMatrix();
+ glDisable(GL_TEXTURE_2D);
+ if(transition<.1)glColor4f(1,0,0,1-(transition*10));
+ if(transition>.9)glColor4f(1,0,0,1-((1-transition)*10));
+ /*glPushMatrix();
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(190, 150, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(640, 150, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(640, 336, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(190, 336, 0.0f);
+ glEnd();
+ glPopMatrix();*/
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+ }
+
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glPushMatrix();
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glPopMatrix();
+ glPushMatrix();
+ glTranslatef(mousecoordh-screenwidth/2,mousecoordv*-1+screenheight/2,0);
+ glScalef((float)screenwidth/64,(float)screenwidth/64,1);
+ glTranslatef(1,-1,0);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(1,1,1,1);
+ glBindTexture( GL_TEXTURE_2D, cursortexture);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glPopMatrix();
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix();
+
+
+ if(flashamount>0)
+ {
+ if(flashamount>1)flashamount=1;
+ if(flashdelay<=0)flashamount-=multiplier;
+ flashdelay--;
+ if(flashamount<0)flashamount=0;
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(flashr,flashg,flashb,flashamount);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+ }
+
+ if(freeze||winfreeze||(mainmenu&&gameon)||(!gameon&&gamestarted)||(!gameon&&gamestarted)){
+ tempmult=multiplier;
+ multiplier=0;
+ }
+
+
+ //glFlush();
+ if(drawmode!=motionblurmode||mainmenu){
+#ifdef WIN32
+ if(drawmode!=motionblurmode) SwapBuffers( hDC);
+#else
+ if(drawmode!=motionblurmode)aglSwapBuffers(gaglContext); // send swap command
+#endif // send swap command
+ }
+
+ //myassert(glGetError() == GL_NO_ERROR);
+ glDrawBuffer(GL_BACK);
+ glReadBuffer(GL_BACK);
+ //glFlush();
+
+ weapons.DoStuff();
+
+ if(drawtoggle==2)drawtoggle=0;
+
+ if(freeze||winfreeze||(mainmenu&&gameon)||(!gameon&&gamestarted)){
+ multiplier=tempmult;
+ }
+ //Jordan fixed your warning!
+ return 0;
+}
--- /dev/null
+#include "Game.h"
+extern float screenwidth,screenheight;
+extern float viewdistance;
+extern XYZ viewer;
+extern XYZ lightlocation;
+extern float lightambient[3],lightbrightness[3];
+extern float fadestart;
+extern float texscale;
+extern float gravity;
+extern Light light;
+extern Animation animation[animation_count];
+extern Skeleton testskeleton;
+extern int numsounds;
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern Terrain terrain;
+extern Sprites sprites;
+extern int kTextureSize;
+extern float texdetail;
+extern float realtexdetail;
+extern float terraindetail;
+extern float volume;
+extern Objects objects;
+extern int detail;
+extern bool cellophane;
+extern GLubyte bloodText[512*512*3];
+extern GLubyte wolfbloodText[512*512*3];
+extern bool ismotionblur;
+extern bool trilinear;
+#ifdef WIN32
+extern HDC hDC;
+#else
+extern AGLContext gaglContext;
+#endif
+extern bool osx;
+extern bool musictoggle;
+extern Weapons weapons;
+extern Person player[maxplayers];
+extern int numplayers;
+extern int environment;
+extern bool ambientsound;
+extern float multiplier;
+extern int newnetmessages;
+extern int netdatanew;
+extern float mapinfo;
+extern bool stillloading;
+extern TGAImageRec texture;
+extern short vRefNum;
+extern long dirID;
+extern int mainmenu;
+extern int oldmainmenu;
+extern bool visibleloading;
+extern int loadscreencolor;
+extern float flashamount,flashr,flashg,flashb;
+extern int flashdelay;
+extern int whichjointstartarray[26];
+extern int whichjointendarray[26];
+extern int difficulty;
+extern float tintr,tintg,tintb;
+extern float slomospeed;
+extern char mapname[256];
+extern bool gamestarted;
+
+extern int numaccounts;
+extern int accountactive;
+extern int accountdifficulty[10];
+extern int accountprogress[10];
+extern float accountpoints[10];
+extern float accounthighscore[10][50];
+extern float accountfasttime[10][50];
+extern bool accountunlocked[10][60];
+extern char accountname[10][256];
+
+extern int numdialogues;
+extern int numdialogueboxes[20];
+extern int dialoguetype[20];
+extern int dialogueboxlocation[20][20];
+extern float dialogueboxcolor[20][20][3];
+extern int dialogueboxsound[20][20];
+extern char dialoguetext[20][20][128];
+extern char dialoguename[20][20][64];
+extern XYZ dialoguecamera[20][20];
+extern float dialoguecamerarotation[20][20];
+extern float dialoguecamerarotation2[20][20];
+extern int indialogue;
+extern int whichdialogue;
+extern float dialoguetime;
+
+extern float accountcampaignhighscore[10];
+extern float accountcampaignfasttime[10];
+extern float accountcampaignscore[10];
+extern float accountcampaigntime[10];
+
+extern int accountcampaignchoicesmade[10];
+extern int accountcampaignchoices[10][5000];
+
+extern FSOUND_STREAM * strm[10];
+
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+extern "C" void PlayStreamEx(int chan, FSOUND_STREAM *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+Game::TextureList Game::textures;
+
+void Game::Dispose()
+{
+ int i,j;
+
+ LOGFUNC;
+
+ if(endgame==2){
+ accountcampaignchoicesmade[accountactive]=0;
+ accountcampaignscore[accountactive]=0;
+ accountcampaigntime[accountactive]=0;
+ endgame=0;
+ }
+
+
+ sprintf (mapname, ":Data:Users");
+
+ FILE *tfile;
+ tfile=fopen( mapname, "wb" );
+ if (tfile)
+ {
+ fpackf(tfile, "Bi", numaccounts);
+ fpackf(tfile, "Bi", accountactive);
+ if(numaccounts>0)
+ {
+ for(i=0;i<numaccounts;i++)
+ {
+ fpackf(tfile, "Bf", accountcampaigntime[i]);
+ fpackf(tfile, "Bf", accountcampaignscore[i]);
+ fpackf(tfile, "Bf", accountcampaignfasttime[i]);
+ fpackf(tfile, "Bf", accountcampaignhighscore[i]);
+ fpackf(tfile, "Bi", accountdifficulty[i]);
+ fpackf(tfile, "Bi", accountprogress[i]);
+ fpackf(tfile, "Bi", accountcampaignchoicesmade[i]);
+ for(j=0;j<accountcampaignchoicesmade[i];j++)
+ {
+ fpackf(tfile, "Bi", accountcampaignchoices[i][j]);
+ }
+ fpackf(tfile, "Bf", accountpoints[i]);
+ for(j=0;j<50;j++)
+ {
+ fpackf(tfile, "Bf", accounthighscore[i][j]);
+ fpackf(tfile, "Bf", accountfasttime[i][j]);
+ }
+ for(j=0;j<60;j++)
+ {
+ fpackf(tfile, "Bb", accountunlocked[i][j]);
+ }
+ fpackf(tfile, "Bi", strlen(accountname[i]));
+ if(strlen(accountname[i])>0)
+ {
+ for(j=0;j<(int)strlen(accountname[i]);j++)
+ {
+ fpackf(tfile, "Bb", accountname[i][j]);
+ }
+ }
+ }
+ }
+
+ fclose(tfile);
+ }
+
+ TexIter it = textures.begin();
+ for (; it != textures.end(); ++it)
+ {
+ if (glIsTexture(it->second))
+ glDeleteTextures(1, &it->second);
+ }
+ textures.clear();
+
+ LOG("Shutting down sound system...");
+
+ FSOUND_StopSound(FSOUND_ALL);
+
+#define streamcount 20
+#define samplecount 100
+
+ for (i=0; i < samplecount; ++i)
+ {
+ FSOUND_Sample_Free(samp[i]);
+ }
+
+ for (i=0; i < streamcount; ++i)
+ {
+ FSOUND_Stream_Close(strm[i]);
+ }
+
+ FSOUND_Close();
+ if (texture.data)
+ {
+ free(texture.data);
+ }
+ texture.data = 0;
+}
+
+
+//void Game::LoadSounds();
+void Game::LoadSounds()
+{
+ LOGFUNC;
+
+ LOG(std::string("Loading sounds..."));
+
+ FSOUND_3D_SetDopplerFactor(0);
+
+ FSOUND_SetSFXMasterVolume((int)(volume*255));
+
+ samp[footstepsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow1.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound], 4.0f, 1000.0f);
+
+ samp[footstepsound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound2], 4.0f, 1000.0f);
+
+ samp[footstepsound3] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone1.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound3], 4.0f, 1000.0f);
+
+ samp[footstepsound4] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound4], 4.0f, 1000.0f);
+
+ samp[landsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:land.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[landsound], 4.0f, 1000.0f);
+
+ samp[jumpsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:jump.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[jumpsound], 4.0f, 1000.0f);
+
+ samp[hawksound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:hawk.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[hawksound], 40.0f, 10000.0f);
+
+ samp[whooshsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:whoosh.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[whooshsound], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMode(samp[whooshsound], FSOUND_LOOP_NORMAL);
+
+ samp[landsound1] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:land1.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[landsound1], 4.0f, 1000.0f);
+
+
+
+ samp[landsound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:land2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[landsound2], 4.0f, 1000.0f);
+
+ samp[breaksound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:broken.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[breaksound], 8.0f, 2000.0f);
+
+ samp[lowwhooshsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Lowwhoosh.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[lowwhooshsound], 8.0f, 2000.0f);
+
+ samp[midwhooshsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:midwhoosh.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[midwhooshsound], 8.0f, 2000.0f);
+
+ samp[highwhooshsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:highwhoosh.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[highwhooshsound], 8.0f, 2000.0f);
+
+ samp[movewhooshsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:movewhoosh.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[movewhooshsound], 8.0f, 2000.0f);
+
+ samp[heavyimpactsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:heavyimpact.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[heavyimpactsound], 8.0f, 2000.0f);
+
+ samp[whooshhitsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Whooshhit.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[whooshhitsound], 8.0f, 2000.0f);
+
+ samp[thudsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:thud.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[thudsound], 8.0f, 2000.0f);
+
+ samp[alarmsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:alarm.ogg", FSOUND_2D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[alarmsound], 8.0f, 2000.0f);
+
+ samp[breaksound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:break.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[breaksound2], 8.0f, 2000.0f);
+
+ samp[knifedrawsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:knifedraw.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[knifedrawsound], 8.0f, 2000.0f);
+
+ samp[knifesheathesound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:knifesheathe.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[knifesheathesound], 8.0f, 2000.0f);
+
+ samp[fleshstabsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Fleshstab.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[fleshstabsound], 8.0f, 2000.0f);
+
+ samp[fleshstabremovesound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Fleshstabremove.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[fleshstabremovesound], 8.0f, 2000.0f);
+
+ samp[knifeswishsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:knifeswish.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[knifeswishsound], 8.0f, 2000.0f);
+
+ samp[knifeslicesound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:knifeslice.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[knifeslicesound], 8.0f, 2000.0f);
+
+ samp[swordslicesound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:swordslice.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[swordslicesound], 8.0f, 2000.0f);
+
+ samp[skidsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:skid.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[skidsound], 8.0f, 2000.0f);
+
+ samp[snowskidsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:snowskid.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[snowskidsound], 8.0f, 2000.0f);
+
+ samp[bushrustle] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:bushrustle.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[bushrustle], 4.0f, 1000.0f);
+
+ samp[clank1sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:clank1.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[clank1sound], 8.0f, 2000.0f);
+
+ samp[clank2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:clank2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[clank2sound], 8.0f, 2000.0f);
+
+ samp[clank3sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:clank3.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[clank3sound], 8.0f, 2000.0f);
+
+ samp[clank4sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:clank4.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[clank4sound], 8.0f, 2000.0f);
+
+ samp[consolesuccesssound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:consolesuccess.ogg", FSOUND_2D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[consolesuccesssound], 4.0f, 1000.0f);
+
+ samp[consolefailsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:consolefail.ogg", FSOUND_2D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[consolefailsound], 4.0f, 1000.0f);
+
+ samp[metalhitsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:MetalHit.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[metalhitsound], 8.0f, 2000.0f);
+
+ samp[clawslicesound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:clawslice.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[clawslicesound], 8.0f, 2000.0f);
+
+ samp[splattersound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:splatter.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[splattersound], 8.0f, 2000.0f);
+
+ samp[growlsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Growl.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[growlsound], 1000.0f, 2000.0f);
+
+ samp[growl2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:Growl2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[growl2sound], 1000.0f, 2000.0f);
+
+ samp[barksound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:bark.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[barksound], 1000.0f, 2000.0f);
+
+ samp[bark2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:bark2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[bark2sound], 1000.0f, 2000.0f);
+
+ samp[bark3sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:bark3.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[bark3sound], 1000.0f, 2000.0f);
+
+ samp[snarlsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:snarl.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[snarlsound], 1000.0f, 2000.0f);
+
+
+ samp[snarl2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:snarl2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[snarl2sound], 1000.0f, 2000.0f);
+
+ samp[barkgrowlsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:barkgrowl.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[barkgrowlsound], 1000.0f, 2000.0f);
+
+ samp[rabbitattacksound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitattack.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitattacksound], 1000.0f, 2000.0f);
+
+ samp[rabbitattack2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitattack2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitattack2sound], 1000.0f, 2000.0f);
+
+ samp[rabbitattack3sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitattack3.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitattack3sound], 1000.0f, 2000.0f);
+
+ samp[rabbitattack4sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitattack4.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitattack4sound], 1000.0f, 2000.0f);
+
+ samp[rabbitpainsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitpain.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitpainsound], 1000.0f, 2000.0f);
+
+ samp[rabbitpain1sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitpain2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitpain1sound], 1000.0f, 2000.0f);
+
+ /*samp[rabbitpain2sound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitpain2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitpain2sound], 1000.0f, 2000.0f);
+ */
+ samp[rabbitchitter] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitchitter.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitchitter], 1000.0f, 2000.0f);
+
+ samp[rabbitchitter2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:rabbitchitter2.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[rabbitchitter2], 1000.0f, 2000.0f);
+
+ samp[swordstaffsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:swordstaff.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[swordstaffsound], 8.0f, 2000.0f);
+
+ samp[staffbodysound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:staffbody.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[staffbodysound], 8.0f, 2000.0f);
+
+ samp[staffheadsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:staffhead.ogg", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[staffheadsound], 8.0f, 2000.0f);
+
+ samp[staffbreaksound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:staffbreak.wav", FSOUND_HW3D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[staffbreaksound], 8.0f, 2000.0f);
+
+
+
+}
+
+void Game::LoadTexture(char *fileName, GLuint *textureid,int mipmap, bool hasalpha)
+{
+ GLuint type;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading texture...") + fileName);
+
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ upload_image( fileNamep ,hasalpha);
+
+// std::string fname(fileName);
+// std::transform(fname.begin(), fname.end(), tolower);
+// TexIter it = textures.find(fname);
+
+ //Is it valid?
+ if(1==1)
+ //if(textures.end() == it)
+ {
+ //Alpha channel?
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!*textureid)glGenTextures( 1, textureid );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, *textureid);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ if(trilinear)if(mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)if(mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+ if(!mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.sizeX, texture.sizeY, 0,
+ // GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, texture.data);
+
+ //gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, texture.data );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+// textures.insert(std::make_pair(fname, *textureid));
+ }
+// else
+// {
+// *textureid = it->second;
+// }
+}
+
+void Game::LoadTextureSave(char *fileName, GLuint *textureid,int mipmap,GLubyte *array, int *skinsize)
+{
+ GLuint type;
+ int i;
+ int bytesPerPixel;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading texture (S)...") + fileName);
+
+ //Load Image
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ upload_image( fileNamep ,0);
+ //LoadTGA( fileName );
+
+// std::string fname(fileName);
+// std::transform(fname.begin(), fname.end(), tolower);
+// TexIter it = textures.find(fname);
+
+ //Is it valid?
+ if(1==1)
+ //if(textures.end() == it)
+ {
+ bytesPerPixel=texture.bpp/8;
+
+ //Alpha channel?
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!*textureid)glGenTextures( 1, textureid );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, *textureid);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ if(trilinear)if(mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)if(mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+ if(!mipmap)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ int tempnum=0;
+ for(i=0;i<(int)(texture.sizeY*texture.sizeX*bytesPerPixel);i++){
+ if((i+1)%4||type==GL_RGB){
+ array[tempnum]=texture.data[i];
+ tempnum++;
+ }
+ }
+
+ *skinsize=texture.sizeX;
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, GL_RGB, GL_UNSIGNED_BYTE, array );
+
+// textures.insert(std::make_pair(fname, *textureid));
+ }
+// else
+// {
+// *textureid = it->second;
+// }
+}
+
+void Game::LoadSave(char *fileName, GLuint *textureid,bool mipmap,GLubyte *array, int *skinsize)
+{
+ int i;
+ int bytesPerPixel;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading (S)...") + fileName);
+
+ //Load Image
+ float temptexdetail=texdetail;
+ texdetail=1;
+ //upload_image( fileName );
+ //LoadTGA( fileName );
+ //Load Image
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ upload_image( fileNamep ,0);
+ texdetail=temptexdetail;
+
+ //Is it valid?
+ if(1==1){
+ bytesPerPixel=texture.bpp/8;
+
+ int tempnum=0;
+ for(i=0;i<(int)(texture.sizeY*texture.sizeX*bytesPerPixel);i++){
+ if((i+1)%4||bytesPerPixel==3){
+ array[tempnum]=texture.data[i];
+ tempnum++;
+ }
+ }
+ }
+}
+
+bool Game::AddClothes(char *fileName, GLuint *textureid,bool mipmap,GLubyte *array, int *skinsize)
+{
+ int i;
+ int bytesPerPixel;
+
+ LOGFUNC;
+
+ //upload_image( fileName );
+ //LoadTGA( fileName );
+ //Load Image
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ bool opened;
+ opened=upload_image( fileNamep ,1);
+
+ float alphanum;
+ //Is it valid?
+ if(opened){
+ if(tintr>1)tintr=1;
+ if(tintg>1)tintg=1;
+ if(tintb>1)tintb=1;
+
+ if(tintr<0)tintr=0;
+ if(tintg<0)tintg=0;
+ if(tintb<0)tintb=0;
+
+ bytesPerPixel=texture.bpp/8;
+
+ int tempnum=0;
+ alphanum=255;
+ for(i=0;i<(int)(texture.sizeY*texture.sizeX*bytesPerPixel);i++){
+ if(bytesPerPixel==3)alphanum=255;
+ else if((i+1)%4==0)alphanum=texture.data[i];
+ //alphanum/=2;
+ if((i+1)%4||bytesPerPixel==3){
+ if((i%4)==0)texture.data[i]*=tintr;
+ if((i%4)==1)texture.data[i]*=tintg;
+ if((i%4)==2)texture.data[i]*=tintb;
+ array[tempnum]=(float)array[tempnum]*(1-alphanum/255)+(float)texture.data[i]*(alphanum/255);
+ tempnum++;
+ }
+ }
+ }
+ else return 0;
+ return 1;
+}
+
+
+//***************> ResizeGLScene() <******/
+GLvoid Game::ReSizeGLScene(float fov, float pnear)
+{
+ if (screenheight==0)
+ {
+ screenheight=1;
+ }
+
+ glViewport(0,0,screenwidth,screenheight);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ gluPerspective(fov,(GLfloat)screenwidth/(GLfloat)screenheight,pnear,viewdistance);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+void Game::LoadingScreen()
+{
+ static float loadprogress,minprogress,maxprogress;
+ static AbsoluteTime time = {0,0};
+ static AbsoluteTime frametime = {0,0};
+ AbsoluteTime currTime = UpTime ();
+ double deltaTime = (float) AbsoluteDeltaToDuration (currTime, frametime);
+
+ if (0 > deltaTime) // if negative microseconds
+ deltaTime /= -1000000.0;
+ else // else milliseconds
+ deltaTime /= 1000.0;
+
+ multiplier=deltaTime;
+ if(multiplier<.001)multiplier=.001;
+ if(multiplier>10)multiplier=10;
+ if(multiplier>.05){
+ frametime = currTime; // reset for next time interval
+
+ float size=1;
+ glLoadIdentity();
+ //Clear to black
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+ loadtime+=multiplier*4;
+
+ loadprogress=loadtime;
+ if(loadprogress>100)loadprogress=100;
+
+ //loadprogress=abs(Random()%100);
+
+ //Background
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, loadscreentexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ glColor4f(loadprogress/100,loadprogress/100,loadprogress/100,1);
+ //glColor4f(1,1,1,1);
+ /*if(loadscreencolor==0)glColor4f(1,1,1,1);
+ if(loadscreencolor==1)glColor4f(1,0,0,1);
+ if(loadscreencolor==2)glColor4f(0,1,0,1);
+ if(loadscreencolor==3)glColor4f(0,0,1,1);
+ if(loadscreencolor==4)glColor4f(1,1,0,1);
+ if(loadscreencolor==5)glColor4f(1,0,1,1);
+ */
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(.1-loadprogress/100,0+loadprogress/100+.3);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(.1-loadprogress/100,0+loadprogress/100+.3);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(.1-loadprogress/100,1+loadprogress/100+.3);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(.1-loadprogress/100,1+loadprogress/100+.3);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glEnable(GL_BLEND);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(.4+loadprogress/100,0+loadprogress/100);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(.4+loadprogress/100,0+loadprogress/100);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(.4+loadprogress/100,1+loadprogress/100);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(.4+loadprogress/100,1+loadprogress/100);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, loadscreentexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glScalef((float)screenwidth/2*(1.5-(loadprogress)/200),(float)screenheight/2*(1.5-(loadprogress)/200),1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glEnable(GL_BLEND);
+ //glColor4f(loadprogress/100,loadprogress/100,loadprogress/100,1);
+ glColor4f(loadprogress/100,loadprogress/100,loadprogress/100,1);
+ /*if(loadscreencolor==0)glColor4f(1,1,1,1);
+ if(loadscreencolor==1)glColor4f(1,0,0,1);
+ if(loadscreencolor==2)glColor4f(0,1,0,1);
+ if(loadscreencolor==3)glColor4f(0,0,1,1);
+ if(loadscreencolor==4)glColor4f(1,1,0,1);
+ if(loadscreencolor==5)glColor4f(1,0,1,1);
+ */
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0+.5,0+.5);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1+.5,0+.5);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1+.5,1+.5);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0+.5,1+.5);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, loadscreentexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glScalef((float)screenwidth/2*(100+loadprogress)/100,(float)screenheight/2*(100+loadprogress)/100,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ glEnable(GL_BLEND);
+ glColor4f(loadprogress/100,loadprogress/100,loadprogress/100,.4);
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0+.2,0+.8);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1+.2,0+.8);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1+.2,1+.8);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0+.2,1+.8);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+
+ //Text
+ /*
+ glEnable(GL_TEXTURE_2D);
+ static char string[256]="";
+ sprintf (string, "LOADING... %d%",(int)loadprogress);
+ glColor4f(1,1,1,.2);
+ text.glPrint(280-280*loadprogress/100/2/4,125-125*loadprogress/100/2/4,string,1,1+loadprogress/100,640,480);
+ glColor4f(1.2-loadprogress/100,1.2-loadprogress/100,1.2-loadprogress/100,1);
+ text.glPrint(280,125,string,1,1,640,480);
+ */
+
+ if(flashamount>0){
+ if(flashamount>1)flashamount=1;
+ if(flashdelay<=0)flashamount-=multiplier;
+ flashdelay--;
+ if(flashamount<0)flashamount=0;
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glScalef(screenwidth,screenheight,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glColor4f(flashr,flashg,flashb,flashamount);
+ glBegin(GL_QUADS);
+ glVertex3f(0, 0, 0.0f);
+ glVertex3f(256, 0, 0.0f);
+ glVertex3f(256, 256, 0.0f);
+ glVertex3f(0, 256, 0.0f);
+ glEnd();
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glEnable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+#ifdef WIN32
+ SwapBuffers( hDC);
+#else
+ aglSwapBuffers(gaglContext);
+#endif
+
+ loadscreencolor=0;
+ }
+}
+
+void Game::FadeLoadingScreen(float howmuch)
+{
+ static float loadprogress,minprogress,maxprogress;
+
+ float size=1;
+ glLoadIdentity();
+ //Clear to black
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ loadprogress=howmuch;
+
+ //loadprogress=abs(Random()%100);
+
+ //Background
+
+ //glEnable(GL_TEXTURE_2D);
+ glDisable(GL_TEXTURE_2D);
+ //glBindTexture( GL_TEXTURE_2D, loadscreentexture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glDepthMask(0);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,screenwidth,0,screenheight,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity(); // Reset The Modelview Matrix
+ glTranslatef(screenwidth/2,screenheight/2,0);
+ glScalef((float)screenwidth/2,(float)screenheight/2,1);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+ glColor4f(loadprogress/100,0,0,1);
+ /*if(loadscreencolor==0)glColor4f(1,1,1,1);
+ if(loadscreencolor==1)glColor4f(1,0,0,1);
+ if(loadscreencolor==2)glColor4f(0,1,0,1);
+ if(loadscreencolor==3)glColor4f(0,0,1,1);
+ if(loadscreencolor==4)glColor4f(1,1,0,1);
+ if(loadscreencolor==5)glColor4f(1,0,1,1);
+ */
+ glPushMatrix();
+ //glScalef(.25,.25,.25);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0,0);
+ glVertex3f(-1, -1, 0.0f);
+ glTexCoord2f(1,0);
+ glVertex3f(1, -1, 0.0f);
+ glTexCoord2f(1,1);
+ glVertex3f(1, 1, 0.0f);
+ glTexCoord2f(0,1);
+ glVertex3f(-1, 1, 0.0f);
+ glEnd();
+ glPopMatrix();
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ //Text
+ /*
+ glEnable(GL_TEXTURE_2D);
+ static char string[256]="";
+ sprintf (string, "LOADING... %d%",(int)loadprogress);
+ glColor4f(1,1,1,.2);
+ text.glPrint(280-280*loadprogress/100/2/4,125-125*loadprogress/100/2/4,string,1,1+loadprogress/100,640,480);
+ glColor4f(1.2-loadprogress/100,1.2-loadprogress/100,1.2-loadprogress/100,1);
+ text.glPrint(280,125,string,1,1,640,480);
+ */
+#ifdef WIN32
+ SwapBuffers( hDC);
+#else
+ aglSwapBuffers(gaglContext); // send swap command
+#endif
+
+ loadscreencolor=0;
+}
+
+
+void Game::InitGame()
+{
+#ifndef WIN32
+ ProcessSerialNumber PSN;
+ ProcessInfoRec pinfo;
+ FSSpec pspec;
+ OSStatus err;
+ /* set up process serial number */
+ PSN.highLongOfPSN = 0;
+ PSN.lowLongOfPSN = kCurrentProcess;
+ /* set up info block */
+ pinfo.processInfoLength = sizeof(pinfo);
+ pinfo.processName = NULL;
+ pinfo.processAppSpec = &pspec;
+ /* grab the vrefnum and directory */
+ err = GetProcessInformation(&PSN, &pinfo);
+ if (err == noErr) {
+ vRefNum = pspec.vRefNum;
+ dirID = pspec.parID;
+ }
+#endif
+
+ LOGFUNC;
+
+ autocam=0;
+
+ int i,j;
+
+ numchallengelevels=14;
+
+ registered=0;
+
+ /*char tempstring[256];
+ sprintf (tempstring, "%s", registrationname);
+ long num1;
+ long num2;
+ long num3;
+ long num4;
+ long long longnum;
+ longnum = MD5_string ( tempstring);
+ //longnum = 1111111111111111;
+ num1 = longnum/100000000;
+ num2 = longnum%100000000;
+ sprintf (tempstring, "%d-%d-%d-%d", num1/10000, num1%10000, num2/10000, num2%10000);
+ */
+
+ FILE *tfile;
+ tfile=fopen( ":Data:Sounds:flame.ogg", "rb" );
+ if(tfile)
+ {
+ long num1;
+ long num2;
+ long long longnum;
+ long long longnuma;
+ long num1a;
+ long num2a;
+
+ int numchars;
+ funpackf(tfile, "Bb", ®istered);
+ if(registered)
+ {
+ funpackf(tfile, "Bi", &numchars);
+ if(numchars>0)
+ {
+ for(j=0;j<numchars;j++)
+ {
+ funpackf(tfile, "Bb", ®istrationname[j]);
+ }
+ registrationname[numchars]='\0';
+ funpackf(tfile, "Bi", &num1);
+ funpackf(tfile, "Bi", &num2);
+ longnum=num2+num1*100000000;
+
+ char tempstring[256];
+ sprintf (tempstring, "%s-windows", registrationname);
+ longnuma = MD5_string ( tempstring);
+ num1a = longnuma/100000000;
+ num2a = longnuma%100000000;
+ //if(num1a==num1&&num2a==num2)registered=1;
+ if(numchars>2)registered=1;
+ else registered=0;
+ }
+ }
+ fclose(tfile);
+ }
+ else registered=0;
+
+ accountactive=-1;
+
+ sprintf (mapname, ":Data:Users");
+ tfile=fopen( mapname, "rb" );
+ if(tfile)
+ {
+ funpackf(tfile, "Bi", &numaccounts);
+ funpackf(tfile, "Bi", &accountactive);
+ if(numaccounts>0)
+ {
+ for(i=0;i<numaccounts;i++)
+ {
+ funpackf(tfile, "Bf", &accountcampaigntime[i]);
+ funpackf(tfile, "Bf", &accountcampaignscore[i]);
+ funpackf(tfile, "Bf", &accountcampaignfasttime[i]);
+ funpackf(tfile, "Bf", &accountcampaignhighscore[i]);
+ funpackf(tfile, "Bi", &accountdifficulty[i]);
+ funpackf(tfile, "Bi", &accountprogress[i]);
+ funpackf(tfile, "Bi", &accountcampaignchoicesmade[i]);
+ for(j=0;j<accountcampaignchoicesmade[i];j++)
+ {
+ funpackf(tfile, "Bi", &accountcampaignchoices[i][j]);
+ if (accountcampaignchoices[i][j] >= 10)
+ {
+ accountcampaignchoices[i][j] = 0;
+ }
+ }
+ funpackf(tfile, "Bf", &accountpoints[i]);
+ for(j=0;j<50;j++)
+ {
+ funpackf(tfile, "Bf", &accounthighscore[i][j]);
+ funpackf(tfile, "Bf", &accountfasttime[i][j]);
+ }
+ for(j=0;j<60;j++)
+ {
+ funpackf(tfile, "Bb", &accountunlocked[i][j]);
+ }
+ int temp;
+ funpackf(tfile, "Bi", &temp);
+ if(temp>0)
+ {
+ for(j=0;j<temp;j++)
+ {
+ funpackf(tfile, "Bb", &accountname[i][j]);
+ }
+ }
+ }
+ }
+
+ fclose(tfile);
+ }
+
+ tintr=1;
+ tintg=1;
+ tintb=1;
+
+ whichjointstartarray[0]=righthip;
+ whichjointendarray[0]=rightfoot;
+
+ whichjointstartarray[1]=righthip;
+ whichjointendarray[1]=rightankle;
+
+ whichjointstartarray[2]=righthip;
+ whichjointendarray[2]=rightknee;
+
+ whichjointstartarray[3]=rightknee;
+ whichjointendarray[3]=rightankle;
+
+ whichjointstartarray[4]=rightankle;
+ whichjointendarray[4]=rightfoot;
+
+ whichjointstartarray[5]=lefthip;
+ whichjointendarray[5]=leftfoot;
+
+ whichjointstartarray[6]=lefthip;
+ whichjointendarray[6]=leftankle;
+
+ whichjointstartarray[7]=lefthip;
+ whichjointendarray[7]=leftknee;
+
+ whichjointstartarray[8]=leftknee;
+ whichjointendarray[8]=leftankle;
+
+ whichjointstartarray[9]=leftankle;
+ whichjointendarray[9]=leftfoot;
+
+ whichjointstartarray[10]=abdomen;
+ whichjointendarray[10]=rightshoulder;
+
+ whichjointstartarray[11]=abdomen;
+ whichjointendarray[11]=rightelbow;
+
+ whichjointstartarray[12]=abdomen;
+ whichjointendarray[12]=rightwrist;
+
+ whichjointstartarray[13]=abdomen;
+ whichjointendarray[13]=righthand;
+
+ whichjointstartarray[14]=rightshoulder;
+ whichjointendarray[14]=rightelbow;
+
+ whichjointstartarray[15]=rightelbow;
+ whichjointendarray[15]=rightwrist;
+
+ whichjointstartarray[16]=rightwrist;
+ whichjointendarray[16]=righthand;
+
+ whichjointstartarray[17]=abdomen;
+ whichjointendarray[17]=leftshoulder;
+
+ whichjointstartarray[18]=abdomen;
+ whichjointendarray[18]=leftelbow;
+
+ whichjointstartarray[19]=abdomen;
+ whichjointendarray[19]=leftwrist;
+
+ whichjointstartarray[20]=abdomen;
+ whichjointendarray[20]=lefthand;
+
+ whichjointstartarray[21]=leftshoulder;
+ whichjointendarray[21]=leftelbow;
+
+ whichjointstartarray[22]=leftelbow;
+ whichjointendarray[22]=leftwrist;
+
+ whichjointstartarray[23]=leftwrist;
+ whichjointendarray[23]=lefthand;
+
+ whichjointstartarray[24]=abdomen;
+ whichjointendarray[24]=neck;
+
+ whichjointstartarray[25]=neck;
+ whichjointendarray[25]=head;
+
+ FadeLoadingScreen(0);
+
+ stillloading=1;
+
+ texture.data = ( GLubyte* )malloc( 1024*1024*4 );
+
+ int temptexdetail=texdetail;
+ texdetail=1;
+ text.LoadFontTexture(":Data:Textures:Font.png");
+ text.BuildFont();
+ texdetail=temptexdetail;
+
+ FadeLoadingScreen(10);
+
+ if(detail==2){
+ texdetail=1;
+ terraindetail=1;
+ }
+ if(detail==1){
+ texdetail=2;
+ terraindetail=1;
+ }
+ if(detail==0){
+ texdetail=4;
+ terraindetail=1;
+ //terraindetail=2;
+ }
+
+ for (int it = 0; it < 100; ++it)
+ {
+ channels[it] = -1;
+ samp[it] = NULL;
+ }
+ for (int it = 0; it < 20; ++it)
+ {
+ strm[it] = NULL;
+ }
+
+ LOG("Initializing sound system...");
+
+ FSOUND_Init(44100, 32, 0);
+
+ FSOUND_SetSFXMasterVolume((int)(volume*255));
+
+ strm[stream_music3] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:music3.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=0;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_music3], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_music3], FSOUND_LOOP_NORMAL);
+
+ if(musictoggle){
+// PlaySoundEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ PlayStreamEx(stream_music3, strm[stream_music3], 0, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+ }
+
+ FadeLoadingScreen(20);
+
+ if(ambientsound){
+ strm[stream_wind] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:wind.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_wind], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_wind], FSOUND_LOOP_NORMAL);
+
+ FadeLoadingScreen(30);
+
+ strm[stream_desertambient] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:desertambient.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_desertambient], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_desertambient], FSOUND_LOOP_NORMAL);
+ }
+
+ FadeLoadingScreen(40);
+
+ samp[firestartsound] = FSOUND_Sample_Load(FSOUND_FREE, ConvertFileName(":Data:Sounds:firestart.ogg"), FSOUND_2D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ strm[stream_firesound] = FSOUND_Stream_Open(":Data:Sounds:fire.ogg", FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_firesound], 8.0f, 2000.0f);
+ FSOUND_Stream_SetMode(strm[stream_firesound], FSOUND_LOOP_NORMAL);
+
+ FadeLoadingScreen(50);
+
+ samp[fireendsound] = FSOUND_Sample_Load(FSOUND_FREE, ConvertFileName(":Data:Sounds:fireend.ogg"), FSOUND_2D, 0); if(visibleloading){LoadingScreen(); loadscreencolor=5;}
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ //if(musictoggle){
+ strm[stream_music1grass] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:music1grass.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=1;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_music1grass], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_music1grass], FSOUND_LOOP_NORMAL);
+
+ strm[stream_music1snow] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:music1snow.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=2;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_music1snow], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_music1snow], FSOUND_LOOP_NORMAL);
+
+ FadeLoadingScreen(60);
+
+ strm[stream_music1desert] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:music1desert.mp3"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=3;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_music1desert], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_music1desert], FSOUND_LOOP_NORMAL);
+
+ FadeLoadingScreen(80);
+ strm[stream_music2] = FSOUND_Stream_Open(ConvertFileName(":Data:Sounds:music2.ogg"), FSOUND_2D, 0, 0); if(visibleloading){LoadingScreen(); loadscreencolor=4;}
+// FSOUND_Sample_SetMinMaxDistance(strm[stream_music2], 4.0f, 1000.0f);
+ FSOUND_Stream_SetMode(strm[stream_music2], FSOUND_LOOP_NORMAL);
+
+ //}
+
+
+ FadeLoadingScreen(90);
+
+
+ LoadTexture(":Data:Textures:Cursor.png",&cursortexture,0,1);
+
+ LoadTexture(":Data:Textures:MapCircle.png",&Mapcircletexture,0,1);
+ LoadTexture(":Data:Textures:MapBox.png",&Mapboxtexture,0,1);
+ LoadTexture(":Data:Textures:MapArrow.png",&Maparrowtexture,0,1);
+
+ temptexdetail=texdetail;
+ if(texdetail>2)texdetail=2;
+ LoadTexture(":Data:Textures:Lugaru.png",&Mainmenuitems[0],0,0);
+ LoadTexture(":Data:Textures:Newgame.png",&Mainmenuitems[1],0,0);
+ LoadTexture(":Data:Textures:Options.png",&Mainmenuitems[2],0,0);
+ LoadTexture(":Data:Textures:Quit.png",&Mainmenuitems[3],0,0);
+ LoadTexture(":Data:Textures:World.png",&Mainmenuitems[7],0,0);
+ LoadTexture(":Data:Textures:Eyelid.png",&Mainmenuitems[4],0,1);
+ //LoadTexture(":Data:Textures:Eye.jpg",&Mainmenuitems[5],0,1);
+ texdetail=temptexdetail;
+
+ loaddistrib=0;
+ anim=0;
+
+ FadeLoadingScreen(95);
+
+
+ gameon=0;
+ mainmenu=1;
+
+ stillloading=0;
+ firstload=0;
+ oldmainmenu=0;
+
+ newdetail=detail;
+ newscreenwidth=screenwidth;
+ newscreenheight=screenheight;
+
+
+
+ /*
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ */
+}
+
+
+void Game::LoadStuff()
+{
+ static float temptexdetail;
+ static float viewdistdetail;
+ static int i,j,texsize;
+ float megascale =1;
+
+ LOGFUNC;
+
+ visibleloading=1;
+
+ /*musicvolume[3]=512;
+ PlaySoundEx( music4, samp[music4], NULL, TRUE);
+ FSOUND_SetPaused(channels[music4], FALSE);
+ FSOUND_SetVolume(channels[music4], 512);
+ */
+ loadtime=0;
+
+ stillloading=1;
+
+ //texture.data = ( GLubyte* )malloc( 1024*1024*4 );
+
+ newnetmessages=0;
+
+ for(i=0;i<maxplayers;i++)
+ {
+ if (glIsTexture(player[i].skeleton.drawmodel.textureptr))
+ {
+ glDeleteTextures(1, &player[i].skeleton.drawmodel.textureptr);
+ }
+ player[i].skeleton.drawmodel.textureptr=0;;
+ }
+
+ //temptexdetail=texdetail;
+ //texdetail=1;
+ i=abs(Random()%4);
+ LoadTexture(":Data:Textures:fire.jpg",&loadscreentexture,1,0);
+ //texdetail=temptexdetail;
+
+ temptexdetail=texdetail;
+ texdetail=1;
+ text.LoadFontTexture(":Data:Textures:Font.png");
+ text.BuildFont();
+ texdetail=temptexdetail;
+
+ numsounds=71;
+
+ viewdistdetail=2;
+ viewdistance=50*megascale*viewdistdetail;
+
+ brightness=100;
+
+
+
+ if(detail==2){
+ texdetail=1;
+ terraindetail=1;
+ }
+ if(detail==1){
+ texdetail=2;
+ terraindetail=1;
+ }
+ if(detail==0){
+ texdetail=4;
+ terraindetail=1;
+ //terraindetail=2;
+ }
+
+ realtexdetail=texdetail;
+
+ /*texdetail/=4;
+ if(texdetail<1)texdetail=1;
+ realtexdetail=texdetail*4;
+ */
+ numplayers=1;
+
+
+
+ /*LoadTexture(":Data:Textures:snow.png",&terraintexture,1);
+
+ LoadTexture(":Data:Textures:rock.png",&terraintexture2,1);
+
+ LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
+ */
+
+
+ LOG("Loading weapon data...");
+
+ LoadTexture(":Data:Textures:knife.png",&weapons.knifetextureptr,0,1);
+ LoadTexture(":Data:Textures:bloodknife.png",&weapons.bloodknifetextureptr,0,1);
+ LoadTexture(":Data:Textures:lightbloodknife.png",&weapons.lightbloodknifetextureptr,0,1);
+ LoadTexture(":Data:Textures:sword.jpg",&weapons.swordtextureptr,1,0);
+ LoadTexture(":Data:Textures:Swordblood.jpg",&weapons.bloodswordtextureptr,1,0);
+ LoadTexture(":Data:Textures:Swordbloodlight.jpg",&weapons.lightbloodswordtextureptr,1,0);
+ LoadTexture(":Data:Textures:Staff.jpg",&weapons.stafftextureptr,1,0);
+
+ weapons.throwingknifemodel.load((char *)":Data:Models:throwingknife.solid",1);
+ weapons.throwingknifemodel.Scale(.001,.001,.001);
+ //weapons.throwingknifemodel.Rotate(0,0,-90);
+ weapons.throwingknifemodel.Rotate(90,0,0);
+ weapons.throwingknifemodel.Rotate(0,90,0);
+ weapons.throwingknifemodel.flat=0;
+ weapons.throwingknifemodel.CalculateNormals(1);
+ //weapons.throwingknifemodel.ScaleNormals(-1,-1,-1);
+
+ weapons.swordmodel.load((char *)":Data:Models:sword.solid",1);
+ weapons.swordmodel.Scale(.001,.001,.001);
+ //weapons.swordmodel.Rotate(0,0,-90);
+ weapons.swordmodel.Rotate(90,0,0);
+ weapons.swordmodel.Rotate(0,90,0);
+ weapons.swordmodel.Rotate(0,0,90);
+ weapons.swordmodel.flat=1;
+ weapons.swordmodel.CalculateNormals(1);
+ //weapons.swordmodel.ScaleNormals(-1,-1,-1);
+
+ weapons.staffmodel.load((char *)":Data:Models:staff.solid",1);
+ weapons.staffmodel.Scale(.005,.005,.005);
+ //weapons.staffmodel.Rotate(0,0,-90);
+ weapons.staffmodel.Rotate(90,0,0);
+ weapons.staffmodel.Rotate(0,90,0);
+ weapons.staffmodel.Rotate(0,0,90);
+ weapons.staffmodel.flat=1;
+ weapons.staffmodel.CalculateNormals(1);
+ //weapons.staffmodel.ScaleNormals(-1,-1,-1);
+
+ //temptexdetail=texdetail;
+ //if(texdetail>4)texdetail=4;
+ LoadTexture(":Data:Textures:shadow.png",&terrain.shadowtexture,0,1);
+
+ LoadTexture(":Data:Textures:blood.png",&terrain.bloodtexture,0,1);
+
+ LoadTexture(":Data:Textures:break.png",&terrain.breaktexture,0,1);
+
+ LoadTexture(":Data:Textures:blood.png",&terrain.bloodtexture2,0,1);
+
+
+ LoadTexture(":Data:Textures:footprint.png",&terrain.footprinttexture,0,1);
+
+ LoadTexture(":Data:Textures:bodyprint.png",&terrain.bodyprinttexture,0,1);
+
+ /*LoadTexture(":Data:Textures:cloud.png",&sprites.cloudtexture,1);
+
+ LoadTexture(":Data:Textures:cloudimpact.png",&sprites.cloudimpacttexture,1);
+
+ LoadTexture(":Data:Textures:bloodparticle.png",&sprites.bloodtexture,1);
+
+ LoadTexture(":Data:Textures:snowflake.png",&sprites.snowflaketexture,1);
+
+ LoadTexture(":Data:Textures:flame.png",&sprites.flametexture,1);
+
+ LoadTexture(":Data:Textures:smoke.png",&sprites.smoketexture,1);
+ //texdetail=temptexdetail;
+ LoadTexture(":Data:Textures:shine.png",&sprites.shinetexture,1);*/
+
+
+
+ LoadTexture(":Data:Textures:hawk.png",&hawktexture,0,1);
+
+ LoadTexture(":Data:Textures:logo.png",&logotexture,0,1);
+
+
+ //LoadTexture(":Data:Textures:box.jpg",&objects.boxtextureptr,1,0);
+
+
+ LoadTexture(":Data:Textures:cloud.png",&sprites.cloudtexture,1,1);
+ LoadTexture(":Data:Textures:cloudimpact.png",&sprites.cloudimpacttexture,1,1);
+ LoadTexture(":Data:Textures:bloodparticle.png",&sprites.bloodtexture,1,1);
+ LoadTexture(":Data:Textures:snowflake.png",&sprites.snowflaketexture,1,1);
+ LoadTexture(":Data:Textures:flame.png",&sprites.flametexture,1,1);
+ LoadTexture(":Data:Textures:bloodflame.png",&sprites.bloodflametexture,1,1);
+ LoadTexture(":Data:Textures:smoke.png",&sprites.smoketexture,1,1);
+ LoadTexture(":Data:Textures:shine.png",&sprites.shinetexture,1,0);
+ LoadTexture(":Data:Textures:splinter.png",&sprites.splintertexture,1,1);
+ LoadTexture(":Data:Textures:leaf.png",&sprites.leaftexture,1,1);
+ LoadTexture(":Data:Textures:tooth.png",&sprites.toothtexture,1,1);
+
+ rotation=0;
+ rotation2=0;
+ ReSizeGLScene(90,.01);
+
+ viewer=0;
+
+
+
+
+ if(detail)kTextureSize=1024;
+ if(detail==1)kTextureSize=512;
+ if(detail==0)kTextureSize=256;
+
+
+ //drawmode=motionblurmode;
+
+ //Set up distant light
+ light.color[0]=.95;
+ light.color[1]=.95;
+ light.color[2]=1;
+ light.ambient[0]=.2;
+ light.ambient[1]=.2;
+ light.ambient[2]=.24;
+ light.location.x=1;
+ light.location.y=1;
+ light.location.z=-.2;
+ Normalise(&light.location);
+
+ LoadingScreen();
+
+ SetUpLighting();
+
+
+ fadestart=.6;
+ gravity=-10;
+
+ texscale=.2/megascale/viewdistdetail;
+ terrain.scale=3*megascale*terraindetail*viewdistdetail;
+
+ viewer.x=terrain.size/2*terrain.scale;
+ viewer.z=terrain.size/2*terrain.scale;
+
+ hawk.load((char *)":Data:Models:hawk.solid",1);
+ hawk.Scale(.03,.03,.03);
+ hawk.Rotate(90,1,1);
+ hawk.CalculateNormals(0);
+ hawk.ScaleNormals(-1,-1,-1);
+ hawkcoords.x=terrain.size/2*terrain.scale-5-7;
+ hawkcoords.z=terrain.size/2*terrain.scale-5-7;
+ hawkcoords.y=terrain.getHeight(hawkcoords.x,hawkcoords.z)+25;
+
+
+ eye.load((char *)":Data:Models:eye.solid",1);
+ eye.Scale(.03,.03,.03);
+ eye.CalculateNormals(0);
+
+ cornea.load((char *)":Data:Models:cornea.solid",1);
+ cornea.Scale(.03,.03,.03);
+ cornea.CalculateNormals(0);
+
+ iris.load((char *)":Data:Models:iris.solid",1);
+ iris.Scale(.03,.03,.03);
+ iris.CalculateNormals(0);
+
+ LoadSave(":Data:Textures:Bloodfur.png",0,1,&bloodText[0],0);
+ LoadSave(":Data:Textures:Wolfbloodfur.png",0,1,&wolfbloodText[0],0);
+
+ oldenvironment=-4;
+
+ gameon=1;
+ mainmenu=0;
+
+ firstload=0;
+ //if(targetlevel!=7)
+ Loadlevel(targetlevel);
+
+
+ rabbitcoords=player[0].coords;
+ rabbitcoords.y=terrain.getHeight(rabbitcoords.x,rabbitcoords.z);
+
+ animation[runanim].Load((char *)":Data:Animations:Run",middleheight,neutral);
+
+ animation[bounceidleanim].Load((char *)":Data:Animations:Idle",middleheight,neutral);
+ animation[stopanim].Load((char *)":Data:Animations:Stop",middleheight,neutral);
+
+ animation[jumpupanim].Load((char *)":Data:Animations:JumpUp",highheight,neutral);
+ animation[jumpdownanim].Load((char *)":Data:Animations:JumpDown",highheight,neutral);
+
+ animation[landanim].Load((char *)":Data:Animations:Landing",lowheight,neutral);
+ animation[landhardanim].Load((char *)":Data:Animations:Landhard",lowheight,neutral);
+ animation[climbanim].Load((char *)":Data:Animations:Climb",lowheight,neutral);
+ animation[hanganim].Load((char *)":Data:Animations:Hangon",lowheight,neutral);
+ animation[spinkickanim].Load((char *)":Data:Animations:SpinKick",middleheight,normalattack);
+
+ animation[getupfromfrontanim].Load((char *)":Data:Animations:GetUpFromFront",lowheight,neutral);
+ animation[getupfrombackanim].Load((char *)":Data:Animations:GetUpFromBack",lowheight,neutral);
+ animation[crouchanim].Load((char *)":Data:Animations:Crouch",lowheight,neutral);
+ animation[sneakanim].Load((char *)":Data:Animations:Sneak",lowheight,neutral);
+ animation[rollanim].Load((char *)":Data:Animations:Roll",lowheight,neutral);
+ animation[flipanim].Load((char *)":Data:Animations:Flip",highheight,neutral);
+ animation[frontflipanim].Load((char *)":Data:Animations:Flip",highheight,neutral);
+ animation[spinkickreversedanim].Load((char *)":Data:Animations:SpinKickCaught",middleheight,reversed);
+
+ animation[spinkickreversalanim].Load((char *)":Data:Animations:SpinKickCatch",middleheight,reversal);
+ animation[lowkickanim].Load((char *)":Data:Animations:lowkick",middleheight,normalattack);
+ animation[sweepanim].Load((char *)":Data:Animations:sweep",lowheight,normalattack);
+ animation[sweepreversedanim].Load((char *)":Data:Animations:SweepCaught",lowheight,reversed);
+ animation[sweepreversalanim].Load((char *)":Data:Animations:SweepCatch",middleheight,reversal);
+ animation[rabbitkickanim].Load((char *)":Data:Animations:RabbitKick",middleheight,normalattack);
+ animation[rabbitkickreversedanim].Load((char *)":Data:Animations:RabbitKickCaught",middleheight,reversed);
+ animation[rabbitkickreversalanim].Load((char *)":Data:Animations:RabbitKickCatch",lowheight,reversal);
+ animation[upunchanim].Load((char *)":Data:Animations:Upunch",middleheight,normalattack);
+ animation[staggerbackhighanim].Load((char *)":Data:Animations:Staggerbackhigh",middleheight,neutral);
+ animation[upunchreversedanim].Load((char *)":Data:Animations:UpunchCaught",middleheight,reversed);
+
+ animation[upunchreversalanim].Load((char *)":Data:Animations:UpunchCatch",middleheight,reversal);
+ animation[hurtidleanim].Load((char *)":Data:Animations:Hurtidle",middleheight,neutral);
+ animation[backhandspringanim].Load((char *)":Data:Animations:Backhandspring",middleheight,neutral);
+ animation[fightidleanim].Load((char *)":Data:Animations:Fightidle",middleheight,neutral);
+ animation[walkanim].Load((char *)":Data:Animations:Walk",middleheight,neutral);
+
+ animation[fightsidestep].Load((char *)":Data:Animations:Fightsidestep",middleheight,neutral);
+ animation[killanim].Load((char *)":Data:Animations:Kill",middleheight,normalattack);
+ animation[sneakattackanim].Load((char *)":Data:Animations:Sneakattack",middleheight,reversal);
+ animation[sneakattackedanim].Load((char *)":Data:Animations:Sneakattacked",middleheight,reversed);
+ animation[drawrightanim].Load((char *)":Data:Animations:drawright",middleheight,neutral);
+ animation[knifeslashstartanim].Load((char *)":Data:Animations:slashstart",middleheight,normalattack);
+ animation[crouchdrawrightanim].Load((char *)":Data:Animations:crouchdrawright",lowheight,neutral);
+ animation[crouchstabanim].Load((char *)":Data:Animations:crouchstab",lowheight,normalattack);
+
+ animation[knifefollowanim].Load((char *)":Data:Animations:slashfollow",middleheight,reversal);
+ animation[knifefollowedanim].Load((char *)":Data:Animations:slashfollowed",middleheight,reversed);
+ animation[knifethrowanim].Load((char *)":Data:Animations:knifethrow",middleheight,normalattack);
+ animation[removeknifeanim].Load((char *)":Data:Animations:removeknife",middleheight,neutral);
+ animation[crouchremoveknifeanim].Load((char *)":Data:Animations:crouchremoveknife",lowheight,neutral);
+ animation[jumpreversedanim].Load((char *)":Data:Animations:JumpCaught",middleheight,reversed);
+ animation[jumpreversalanim].Load((char *)":Data:Animations:JumpCatch",middleheight,reversal);
+ animation[staggerbackhardanim].Load((char *)":Data:Animations:Staggerbackhard",middleheight,neutral);
+
+ animation[dropkickanim].Load((char *)":Data:Animations:Dropkick",middleheight,normalattack);
+ animation[winduppunchanim].Load((char *)":Data:Animations:Winduppunch",middleheight,normalattack);
+ animation[winduppunchblockedanim].Load((char *)":Data:Animations:Winduppunchblocked",middleheight,normalattack);
+ animation[blockhighleftanim].Load((char *)":Data:Animations:Blockhighleft",middleheight,normalattack);
+ animation[blockhighleftstrikeanim].Load((char *)":Data:Animations:Blockhighleftstrike",middleheight,normalattack);
+ animation[backflipanim].Load((char *)":Data:Animations:Backflip",highheight,neutral);
+ animation[walljumpbackanim].Load((char *)":Data:Animations:Walljumpback",highheight,neutral);
+ animation[walljumpfrontanim].Load((char *)":Data:Animations:Walljumpfront",highheight,neutral);
+ animation[rightflipanim].Load((char *)":Data:Animations:Rightflip",highheight,neutral);
+ animation[walljumprightanim].Load((char *)":Data:Animations:Walljumpright",highheight,neutral);
+ animation[leftflipanim].Load((char *)":Data:Animations:Leftflip",highheight,neutral);
+ animation[walljumpleftanim].Load((char *)":Data:Animations:Walljumpleft",highheight,neutral);
+ animation[walljumprightkickanim].Load((char *)":Data:Animations:Walljumprightkick",highheight,neutral);
+ animation[walljumpleftkickanim].Load((char *)":Data:Animations:Walljumpleftkick",highheight,neutral);
+ animation[knifefightidleanim].Load((char *)":Data:Animations:Knifefightidle",middleheight,neutral);
+ animation[knifesneakattackanim].Load((char *)":Data:Animations:Knifesneakattack",middleheight,reversal);
+ animation[knifesneakattackedanim].Load((char *)":Data:Animations:Knifesneakattacked",middleheight,reversed);
+ animation[swordfightidleanim].Load((char *)":Data:Animations:swordfightidle",middleheight,neutral);
+ animation[drawleftanim].Load((char *)":Data:Animations:drawleft",middleheight,neutral);
+ animation[swordslashanim].Load((char *)":Data:Animations:swordslash",middleheight,normalattack);
+ animation[swordgroundstabanim].Load((char *)":Data:Animations:swordgroundstab",lowheight,normalattack);
+ animation[dodgebackanim].Load((char *)":Data:Animations:dodgeback",middleheight,neutral);
+ animation[swordsneakattackanim].Load((char *)":Data:Animations:Swordsneakattack",middleheight,reversal);
+ animation[swordsneakattackedanim].Load((char *)":Data:Animations:Swordsneakattacked",middleheight,reversed);
+ animation[swordslashreversedanim].Load((char *)":Data:Animations:swordslashCaught",middleheight,reversed);
+ animation[swordslashreversalanim].Load((char *)":Data:Animations:swordslashCatch",middleheight,reversal);
+ animation[knifeslashreversedanim].Load((char *)":Data:Animations:knifeslashCaught",middleheight,reversed);
+ animation[knifeslashreversalanim].Load((char *)":Data:Animations:knifeslashCatch",middleheight,reversal);
+ animation[swordfightidlebothanim].Load((char *)":Data:Animations:swordfightidleboth",middleheight,neutral);
+ animation[swordslashparryanim].Load((char *)":Data:Animations:sworduprightparry",middleheight,normalattack);
+ animation[swordslashparriedanim].Load((char *)":Data:Animations:swordslashparried",middleheight,normalattack);
+ animation[wolfidle].Load((char *)":Data:Animations:Wolfidle",middleheight,neutral);
+ animation[wolfcrouchanim].Load((char *)":Data:Animations:Wolfcrouch",lowheight,neutral);
+ animation[wolflandanim].Load((char *)":Data:Animations:Wolflanding",lowheight,neutral);
+ animation[wolflandhardanim].Load((char *)":Data:Animations:Wolflandhard",lowheight,neutral);
+ animation[wolfrunanim].Load((char *)":Data:Animations:Wolfrun",middleheight,neutral);
+ animation[wolfrunninganim].Load((char *)":Data:Animations:Wolfrunning",middleheight,neutral);
+ animation[rabbitrunninganim].Load((char *)":Data:Animations:Rabbitrunning",middleheight,neutral);
+ animation[wolfstopanim].Load((char *)":Data:Animations:Wolfstop",middleheight,neutral);
+ animation[rabbittackleanim].Load((char *)":Data:Animations:Rabbittackle",middleheight,neutral);
+ animation[rabbittacklinganim].Load((char *)":Data:Animations:Rabbittackling",middleheight,reversal);
+ animation[rabbittackledbackanim].Load((char *)":Data:Animations:Rabbittackledback",middleheight,reversed);
+ animation[rabbittackledfrontanim].Load((char *)":Data:Animations:Rabbittackledfront",middleheight,reversed);
+ animation[wolfslapanim].Load((char *)":Data:Animations:Wolfslap",middleheight,normalattack);
+ animation[staffhitanim].Load((char *)":Data:Animations:StaffHit",middleheight,normalattack);
+ animation[staffgroundsmashanim].Load((char *)":Data:Animations:StaffGroundSmash",lowheight,normalattack);
+ animation[staffspinhitanim].Load((char *)":Data:Animations:Spinwhack",middleheight,normalattack);
+ animation[staffhitreversedanim].Load((char *)":Data:Animations:StaffHitCaught",middleheight,reversed);
+ animation[staffhitreversalanim].Load((char *)":Data:Animations:StaffHitCatch",middleheight,reversal);
+ animation[staffspinhitreversedanim].Load((char *)":Data:Animations:SpinWhackCaught",middleheight,reversed);
+ animation[staffspinhitreversalanim].Load((char *)":Data:Animations:SpinWhackCatch",middleheight,reversal);
+
+ animation[sitanim].Load((char *)":Data:Animations:Sit",lowheight,neutral);
+ animation[sleepanim].Load((char *)":Data:Animations:Sleep",lowheight,neutral);
+ animation[talkidleanim].Load((char *)":Data:Animations:TalkIdle",middleheight,neutral);
+
+ animation[sitwallanim].Load((char *)":Data:Animations:Dying",lowheight,neutral);
+ animation[dead1anim].Load((char *)":Data:Animations:Dead1",lowheight,neutral);
+ animation[dead2anim].Load((char *)":Data:Animations:Dead2",lowheight,neutral);
+ animation[dead3anim].Load((char *)":Data:Animations:Dead3",lowheight,neutral);
+ animation[dead4anim].Load((char *)":Data:Animations:Dead4",lowheight,neutral);
+ //Fix knife stab, too lazy to do it manually
+ XYZ moveamount;
+ moveamount=0;
+ moveamount.z=2;
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ for(j=0;j<animation[knifesneakattackanim].numframes;j++){
+ animation[knifesneakattackanim].position[i][j]+=moveamount;
+ }
+ }
+
+ loadscreencolor=4;
+ LoadingScreen();
+
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ for(j=0;j<animation[knifesneakattackedanim].numframes;j++){
+ animation[knifesneakattackedanim].position[i][j]+=moveamount;
+ }
+ }
+
+ loadscreencolor=4;
+ LoadingScreen();
+
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ animation[dead1anim].position[i][1]=animation[dead1anim].position[i][0];
+ animation[dead2anim].position[i][1]=animation[dead2anim].position[i][0];
+ animation[dead3anim].position[i][1]=animation[dead3anim].position[i][0];
+ animation[dead4anim].position[i][1]=animation[dead4anim].position[i][0];
+ }
+ animation[dead1anim].speed[0]=0.001;
+ animation[dead2anim].speed[0]=0.001;
+ animation[dead3anim].speed[0]=0.001;
+ animation[dead4anim].speed[0]=0.001;
+
+ animation[dead1anim].speed[1]=0.001;
+ animation[dead2anim].speed[1]=0.001;
+ animation[dead3anim].speed[1]=0.001;
+ animation[dead4anim].speed[1]=0.001;
+
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ for(j=0;j<animation[swordsneakattackanim].numframes;j++){
+ animation[swordsneakattackanim].position[i][j]+=moveamount;
+ }
+ }
+ loadscreencolor=4;
+ LoadingScreen();
+ for(j=0;j<animation[swordsneakattackanim].numframes;j++){
+ animation[swordsneakattackanim].weapontarget[j]+=moveamount;
+ }
+
+ loadscreencolor=4;
+ LoadingScreen();
+
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ for(j=0;j<animation[swordsneakattackedanim].numframes;j++){
+ animation[swordsneakattackedanim].position[i][j]+=moveamount;
+ }
+ }
+ /*
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ for(j=0;j<animation[sleepanim].numframes;j++){
+ animation[sleepanim].position[i][j]=DoRotation(animation[sleepanim].position[i][j],0,180,0);
+ }
+ }
+ */
+ loadscreencolor=4;
+ LoadingScreen();
+ temptexdetail=texdetail;
+ texdetail=1;
+ texdetail=temptexdetail;
+
+ loadscreencolor=4;
+ LoadingScreen();
+
+ //if(ismotionblur){
+ if(!screentexture){
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ glGenTextures( 1, &screentexture );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture( GL_TEXTURE_2D, screentexture);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTextureSize, kTextureSize, 0);
+ }
+ //}
+
+ LoadSounds();
+
+ /*PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ */
+ if(targetlevel!=7){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+ }
+
+ stillloading=0;
+ loading=0;
+ changedelay=1;
+
+ visibleloading=0;
+}
+
+Game::Game()
+{
+ terraintexture = 0;
+ terraintexture2 = 0;
+ terraintexture3 = 0;
+ screentexture = 0;
+ screentexture2 = 0;
+ logotexture = 0;
+ loadscreentexture = 0;
+ Maparrowtexture = 0;
+ Mapboxtexture = 0;
+ Mapcircletexture = 0;
+ cursortexture = 0;
+
+ memset(Mainmenuitems, 0, sizeof(Mainmenuitems));
+
+ nummenuitems = 0;
+
+ memset(startx, 0, sizeof(startx));
+ memset(starty, 0, sizeof(starty));
+ memset(endx, 0, sizeof(endx));
+ memset(endy, 0, sizeof(endy));
+
+ memset(selectedlong, 0, sizeof(selectedlong));
+ memset(offsetx, 0, sizeof(offsetx));
+ memset(offsety, 0, sizeof(offsety));
+ memset(movex, 0, sizeof(movex));
+ memset(movey, 0, sizeof(movey));
+ memset(endy, 0, sizeof(endy));
+
+ transition = 0;
+ anim = 0;
+ selected = 0;
+ loaddistrib = 0;
+ keyselect = 0;
+ indemo = 0;
+ registered = 0;
+
+ won = 0;
+
+ entername = 0;
+
+ memset(menustring, 0, sizeof(menustring));
+ memset(registrationname, 0, sizeof(registrationname));
+ registrationnumber = 0;
+
+ newdetail = 0;
+ newscreenwidth = 0;
+ newscreenheight = 0;
+
+ gameon = 0;
+ deltah = 0,deltav = 0;
+ mousecoordh = 0,mousecoordv = 0;
+ oldmousecoordh = 0,oldmousecoordv = 0;
+ rotation = 0,rotation2 = 0;
+
+// SkyBox skybox;
+
+ cameramode = 0;
+ cameratogglekeydown = 0;
+ chattogglekeydown = 0;
+ olddrawmode = 0;
+ drawmode = 0;
+ drawmodetogglekeydown = 0;
+ explodetogglekeydown = 0;
+ detailtogglekeydown = 0;
+ firstload = 0;
+ oldbutton = 0;
+
+ leveltime = 0;
+ loadtime = 0;
+
+// Model hawk;
+
+// XYZ hawkcoords;
+// XYZ realhawkcoords;
+
+ hawktexture = 0;
+ hawkrotation = 0;
+ hawkcalldelay = 0;
+/*
+ Model eye;
+ Model iris;
+ Model cornea;
+*/
+ stealthloading = 0;
+
+ campaignnumlevels = 0;
+
+ memset(campaignmapname, 0, sizeof(campaignmapname));
+ memset(campaigndescription, 0, sizeof(campaigndescription));
+ memset(campaignchoosenext, 0, sizeof(campaignchoosenext));
+ memset(campaignnumnext, 0, sizeof(campaignnumnext));
+ memset(campaignnextlevel, 0, sizeof(campaignnextlevel));
+ int campaignchoicesmade;
+ memset(campaignchoices, 0, sizeof(campaignchoices));
+ memset(campaignlocationx, 0, sizeof(campaignlocationx));
+ memset(campaignlocationy, 0, sizeof(campaignlocationy));
+ memset(campaignlocationy, 0, sizeof(campaignlocationy));
+
+ campaignchoicenum = 0;
+
+ memset(campaignchoicewhich, 0, sizeof(campaignchoicewhich));
+
+ whichchoice = 0;
+
+ numlevelspassed = 0;
+
+ memset(levelorder, 0, sizeof(levelorder));
+ memset(levelvisible, 0, sizeof(levelvisible));
+ memset(levelhighlight, 0, sizeof(levelhighlight));
+
+ minimap = 0;
+
+ musictype = 0,oldmusictype = 0,oldoldmusictype = 0;
+ realthreat = 0;
+
+// Model rabbit;
+// XYZ rabbitcoords;
+
+// XYZ mapcenter;
+ mapradius = 0;
+
+// Text text;
+ fps = 0;
+
+// XYZ cameraloc;
+ cameradist = 0;
+
+ envtogglekeydown = 0;
+ slomotogglekeydown = 0;
+ texturesizetogglekeydown = 0;
+ freezetogglekeydown = 0;
+ drawtoggle = 0;
+
+ editorenabled = 0;
+ editortype = 0;
+ editorsize = 0;
+ editorrotation = 0;
+ editorrotation2 = 0;
+
+ brightness = 0;
+
+ quit = 0;
+ tryquit = 0;
+
+// XYZ pathpoint[30];
+ numpathpoints = 0;
+ memset(numpathpointconnect, 0, sizeof(numpathpointconnect));
+ memset(pathpointconnect, 0, sizeof(pathpointconnect));
+ pathpointselected = 0;
+
+ endgame = 0;
+ scoreadded = 0;
+ numchallengelevels = 0;
+
+ console = 0;
+ archiveselected = 0;
+
+ memset(consoletext, 0, sizeof(consoletext));
+ memset(consolechars, 0, sizeof(consolechars));
+ chatting = 0;
+ memset(displaytext, 0, sizeof(displaytext));
+ memset(displaychars, 0, sizeof(displaychars));
+ memset(displaytime, 0, sizeof(displaytime));
+ displayblinkdelay = 0;
+ displayblink = 0;
+ displayselected = 0;
+ consolekeydown = 0;
+ consoletogglekeydown = 0;
+ consoleblinkdelay = 0;
+ consoleblink = 0;
+ consoleselected = 0;
+ memset(togglekey, 0, sizeof(togglekey));
+ memset(togglekeydelay, 0, sizeof(togglekeydelay));
+ registernow = 0;
+ autocam = 0;
+
+ crouchkey = 0,jumpkey = 0,forwardkey = 0,chatkey = 0,backkey = 0,leftkey = 0,rightkey = 0,drawkey = 0,throwkey = 0,attackkey = 0;
+ oldattackkey = 0;
+
+ loading = 0;
+ talkdelay = 0;
+
+ numboundaries = 0;
+// XYZ boundary[360];
+
+ whichlevel = 0;
+ oldenvironment = 0;
+ targetlevel = 0;
+ changedelay = 0;
+
+ memset(musicvolume, 0, sizeof(musicvolume));
+ memset(oldmusicvolume, 0, sizeof(oldmusicvolume));
+ musicselected = 0;
+ change = 0;
+}
--- /dev/null
+#include <direct.h>
+#include <ctime>
+#include "Game.h"
+
+using namespace std;
+
+extern float multiplier;
+extern XYZ viewer;
+extern int environment;
+extern float texscale;
+extern Terrain terrain;
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern Sprites sprites;
+extern int kTextureSize;
+extern float screenwidth,screenheight;
+extern float gravity;
+extern int detail;
+extern float texdetail;
+extern Objects objects;
+extern int slomo;
+extern float slomodelay;
+extern bool floatjump;
+extern float volume;
+extern Animation animation[animation_count];
+extern Light light;
+extern float texdetail;
+extern GLubyte bloodText[512*512*3];
+extern GLubyte wolfbloodText[512*512*3];
+extern float terraindetail;
+extern float camerashake;
+extern float woozy;
+extern float blackout;
+extern bool cellophane;
+extern bool musictoggle;
+extern int difficulty;
+extern Weapons weapons;
+extern Person player[maxplayers];
+extern int numplayers;
+extern int bloodtoggle;
+extern bool invertmouse;
+extern float windvar;
+extern float precipdelay;
+extern XYZ viewerfacing;
+extern bool ambientsound;
+extern bool mousejump;
+extern float viewdistance;
+extern bool freeze;
+extern bool autoslomo;
+extern int newnetmessages;
+extern char netmessages[256];
+extern bool keyboardfrozen;
+extern int netdatanew;
+extern bool loadingstuff;
+extern char mapname[256];
+extern XYZ windvector;
+extern bool buttons[3];
+extern bool debugmode;
+static int music1;
+extern int mainmenu;
+extern int oldmainmenu;
+extern bool visibleloading;
+extern int loadscreencolor;
+extern float flashamount,flashr,flashg,flashb;
+extern int flashdelay;
+extern XYZ envsound[30];
+extern float envsoundvol[30];
+extern int numenvsounds;
+extern float envsoundlife[30];
+extern float usermousesensitivity;
+extern bool ismotionblur;
+extern bool foliage;
+extern bool trilinear;
+extern bool damageeffects;
+extern bool showpoints;
+extern bool texttoggle;
+extern bool alwaysblur;
+extern float gamespeed;
+extern bool decals;
+extern bool vblsync;
+extern bool immediate;
+extern bool velocityblur;
+extern int bonus;
+extern int oldbonus;
+extern float bonusvalue;
+extern float bonustotal;
+extern float bonustime;
+extern float startbonustotal;
+extern float tintr,tintg,tintb;
+extern float bonusnum[100];
+extern bool skyboxtexture;
+extern float skyboxr;
+extern float skyboxg;
+extern float skyboxb;
+extern float skyboxlightr;
+extern float skyboxlightg;
+extern float skyboxlightb;
+extern float fadestart;
+extern float slomospeed;
+extern float slomofreq;
+extern int tutoriallevel;
+extern float smoketex;
+extern float tutorialstagetime;
+extern int tutorialstage;
+extern float tutorialmaxtime;
+extern float tutorialsuccess;
+extern bool againbonus;
+extern bool reversaltrain;
+extern bool canattack;
+extern bool cananger;
+extern float damagedealt;
+extern float damagetaken;
+extern int maptype;
+extern int editoractive;
+extern int editorpathtype;
+extern bool oldbuttons[3];
+
+extern float hostiletime;
+
+extern bool gamestarted;
+
+extern int numhotspots;
+extern int winhotspot;
+extern int windialogue;
+extern int killhotspot;
+extern XYZ hotspot[40];
+extern int hotspottype[40];
+extern float hotspotsize[40];
+extern char hotspottext[40][256];
+extern int currenthotspot;
+
+extern int kBitsPerPixel;
+extern int hostile;
+
+extern int numaccounts;
+extern int accountactive;
+extern int accountdifficulty[10];
+extern int accountprogress[10];
+extern float accountpoints[10];
+extern float accounthighscore[10][50];
+extern float accountfasttime[10][50];
+extern bool accountunlocked[10][60];
+extern char accountname[10][256];
+
+extern bool stillloading;
+extern bool winfreeze;
+
+extern int numfalls;
+extern int numflipfail;
+extern int numseen;
+extern int numstaffattack;
+extern int numswordattack;
+extern int numknifeattack;
+extern int numunarmedattack;
+extern int numescaped;
+extern int numflipped;
+extern int numwallflipped;
+extern int numthrowkill;
+extern int numafterkill;
+extern int numreversals;
+extern int numattacks;
+extern int maxalarmed;
+extern int numresponded;
+
+extern int numdialogues;
+extern int numdialogueboxes[max_dialogues];
+extern int dialoguetype[max_dialogues];
+extern int dialogueboxlocation[max_dialogues][max_dialoguelength];
+extern float dialogueboxcolor[max_dialogues][max_dialoguelength][3];
+extern int dialogueboxsound[max_dialogues][max_dialoguelength];
+extern char dialoguetext[max_dialogues][max_dialoguelength][128];
+extern char dialoguename[max_dialogues][max_dialoguelength][64];
+extern XYZ dialoguecamera[max_dialogues][max_dialoguelength];
+extern XYZ participantlocation[max_dialogues][10];
+extern int participantfocus[max_dialogues][max_dialoguelength];
+extern int participantaction[max_dialogues][max_dialoguelength];
+extern float participantrotation[max_dialogues][10];
+extern XYZ participantfacing[max_dialogues][max_dialoguelength][10];
+extern float dialoguecamerarotation[max_dialogues][max_dialoguelength];
+extern float dialoguecamerarotation2[max_dialogues][max_dialoguelength];
+extern int indialogue;
+extern int whichdialogue;
+extern int directing;
+extern float dialoguetime;
+extern int dialoguegonethrough[20];
+
+extern bool campaign;
+
+extern float oldgamespeed;
+
+extern float accountcampaignhighscore[10];
+extern float accountcampaignfasttime[10];
+extern float accountcampaignscore[10];
+extern float accountcampaigntime[10];
+
+extern int accountcampaignchoicesmade[10];
+extern int accountcampaignchoices[10][5000];
+/********************> Tick() <*****/
+extern FSOUND_STREAM * strm[10];
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+extern "C" void PlayStreamEx(int chan, FSOUND_STREAM *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+extern void ScreenShot(const char * fname);
+void Screenshot (void)
+{
+ char temp[1024];
+ time_t t = time(NULL);
+ struct tm *tme = localtime(&t);
+ sprintf(temp, "Screenshots\\Screenshot_%04d_%02d_%02d--%02d_%02d_%02d.png", tme->tm_year + 1900, tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min, tme->tm_sec);
+
+ mkdir("Screenshots");
+ ScreenShot(temp/*"Screenshots\\Screenshot.png"*/);
+
+ /*FSSpec MAC_file;
+ GraphicsExportComponent QT_exporter;
+ OSErr MAC_error_code;
+ CGrafPtr MAC_currentPort;
+ GDHandle MAC_currentDevice;
+ unsigned char* MAC_pixels;
+ Rect MAC_picture_rectangle;
+ GWorldPtr MAC_offscreen_graphics_port;
+
+ static int numscreenshots=0;
+
+ // Make an FSSpec
+ static char buf[256];
+ if(numscreenshots==0){
+ buf[0]=26;
+ buf[1]=':';
+ buf[2]='S';
+ buf[3]='c';
+ buf[4]='r';
+ buf[5]='e';
+ buf[6]='e';
+ buf[7]='n';
+ buf[8]='s';
+ buf[9]='h';
+ buf[10]='o';
+ buf[11]='t';
+ buf[12]='s';
+ buf[13]=':';
+ buf[14]='S';
+ buf[15]='c';
+ buf[16]='r';
+ buf[17]='e';
+ buf[18]='e';
+ buf[19]='n';
+ buf[20]='s';
+ buf[21]='h';
+ buf[22]='o';
+ buf[23]='t';
+ buf[24]='0';
+ buf[25]='0';
+ buf[26]='0';
+ }
+
+ FInfo *fndrInfo;
+ FSMakeFSSpec(0, 0, (unsigned char*)buf, &MAC_file);
+ while(!FSpGetFInfo (&MAC_file, fndrInfo)){
+ FSMakeFSSpec(0, 0, (unsigned char*)buf, &MAC_file);
+ if(!FSpGetFInfo (&MAC_file, fndrInfo)){
+ numscreenshots++;
+ buf[26]++;
+ if(buf[26]==':'){
+ buf[26]='0';
+ buf[25]++;
+ if(buf[25]==':'){
+ buf[25]='0';
+ buf[24]++;
+ if(buf[24]==':'){
+ buf[24]='9';
+ buf[25]='9';
+ buf[26]='9';
+ }
+ }
+ }
+ }
+ }
+
+
+ // Get the GWorld
+ GWorldPtr MAC_gWorld = (CGrafPtr) FrontWindow();
+ //assert(MAC_gWorld != NULL);
+
+ // Allocate memory for loading image
+ MAC_pixels = new unsigned char[(int)(screenheight * screenwidth * 4)];
+ if (MAC_pixels == NULL) {
+ //UTIL_Error("Could not create Texture data.");
+ return;
+ }
+
+ // Get GWorld
+ ::GetGWorld(&MAC_currentPort, &MAC_currentDevice);
+
+ // Make a picture Rectangle
+ MAC_picture_rectangle.left = 0;
+ MAC_picture_rectangle.right = screenwidth;
+ MAC_picture_rectangle.top = 0;
+ MAC_picture_rectangle.bottom = screenheight;
+
+ // Create new offscreen GWorld
+ MAC_error_code = ::QTNewGWorldFromPtr (&MAC_offscreen_graphics_port, k32ARGBPixelFormat, &MAC_picture_rectangle, NULL, NULL, 0, (char *) MAC_pixels, screenwidth * 4);
+ if (MAC_error_code) {
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ delete MAC_pixels;
+ //UTIL_Error("Could not create offscreen GWorld. ");
+ return;
+
+ }
+
+ // Copy OpenGL Context to new GWorld
+ glReadBuffer(GL_FRONT);
+ glReadPixels(0,0,screenwidth,screenheight,GL_RGBA,GL_UNSIGNED_BYTE,MAC_pixels);
+
+ // Swizzle texture
+ for (unsigned long byte = 0; byte < screenheight * screenwidth * 4; byte+=4) {
+ unsigned char temp = MAC_pixels[byte+0];
+ MAC_pixels[byte+0] = MAC_pixels[byte+3];
+ MAC_pixels[byte+3] = MAC_pixels[byte+2];
+ MAC_pixels[byte+2] = MAC_pixels[byte+1];
+ MAC_pixels[byte+1] = temp;
+ }
+
+ // Flip the image :( This could probably be optimized
+ int vert;
+ int src_index;
+ int dst_index;
+ unsigned char temp;
+ for (int horz = 0; horz < screenwidth; ++horz)
+ for (vert = 0; vert < screenheight / 2; ++vert) {
+ src_index = (screenwidth * vert + horz) * 4;
+ dst_index = (screenwidth * (screenheight - vert - 1) + horz) * 4;
+
+ temp=MAC_pixels[src_index+0];
+ MAC_pixels[src_index+0]=MAC_pixels[dst_index+0];
+ MAC_pixels[dst_index+0]=temp;
+
+ temp=MAC_pixels[src_index+1];
+ MAC_pixels[src_index+1]=MAC_pixels[dst_index+1];
+ MAC_pixels[dst_index+1]=temp;
+
+ temp=MAC_pixels[src_index+2];
+ MAC_pixels[src_index+2]=MAC_pixels[dst_index+2];
+ MAC_pixels[dst_index+2]=temp;
+
+ temp=MAC_pixels[src_index+3];
+ MAC_pixels[src_index+3]=MAC_pixels[dst_index+3];
+ MAC_pixels[dst_index+3]=temp;
+ }
+
+
+
+ // Export the Gworld
+ MAC_error_code = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypeBMP, &QT_exporter);
+ if (MAC_error_code) {
+ //UTIL_Warning("Unable to export screenshot.");
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ ::DisposeGWorld(MAC_offscreen_graphics_port);
+ delete MAC_pixels;
+ return;
+ }
+
+ MAC_error_code = GraphicsExportSetInputGWorld(QT_exporter,MAC_offscreen_graphics_port);
+ if (MAC_error_code) {
+ ::CloseComponent(QT_exporter);
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ ::DisposeGWorld(MAC_offscreen_graphics_port);
+ delete MAC_pixels;
+ //UTIL_Warning("Unable to export screenshot.");
+ return;
+ }
+
+ MAC_error_code = GraphicsExportSetOutputFile(QT_exporter,&MAC_file);
+ if (MAC_error_code) {
+ ::CloseComponent(QT_exporter);
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ ::DisposeGWorld(MAC_offscreen_graphics_port);
+ delete MAC_pixels;
+ //UTIL_Warning("Unable to export screenshot.");
+ return;
+ }
+
+ MAC_error_code = GraphicsExportDoExport(QT_exporter,NULL);
+ if (MAC_error_code) {
+ ::CloseComponent(QT_exporter);
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ ::DisposeGWorld(MAC_offscreen_graphics_port);
+ delete MAC_pixels;
+ //UTIL_Warning("Unable to export screenshot.");
+ return;
+ }
+
+ ::CloseComponent(QT_exporter);
+ ::SetGWorld(MAC_currentPort, MAC_currentDevice);
+ ::DisposeGWorld(MAC_offscreen_graphics_port);
+
+ delete MAC_pixels;*/
+}
+
+
+
+void Game::SetUpLighting(){
+ if(environment==snowyenvironment){
+ light.color[0]=.65;
+ light.color[1]=.65;
+ light.color[2]=.7;
+ light.ambient[0]=.4;
+ light.ambient[1]=.4;
+ light.ambient[2]=.44;
+ }
+ if(environment==desertenvironment){
+ light.color[0]=.95;
+ light.color[1]=.95;
+ light.color[2]=.95;
+ light.ambient[0]=.4;
+ light.ambient[1]=.35;
+ light.ambient[2]=.3;
+ }
+
+ if(environment==grassyenvironment){
+ light.color[0]=.95;
+ light.color[1]=.95;
+ light.color[2]=1;
+ light.ambient[0]=.4;
+ light.ambient[1]=.4;
+ light.ambient[2]=.44;
+ }
+ if(!skyboxtexture){
+ light.color[0]=1;
+ light.color[1]=1;
+ light.color[2]=1;
+ light.ambient[0]=.4;
+ light.ambient[1]=.4;
+ light.ambient[2]=.4;
+ }
+ float average;
+ average=(skyboxlightr+skyboxlightg+skyboxlightb)/3;
+ light.color[0]*=(skyboxlightr+average)/2;
+ light.color[1]*=(skyboxlightg+average)/2;
+ light.color[2]*=(skyboxlightb+average)/2;
+ light.ambient[0]=light.ambient[0]*(skyboxlightr+average)/2*1;
+ light.ambient[1]=light.ambient[1]*(skyboxlightg+average)/2*1;
+ light.ambient[2]=light.ambient[2]*(skyboxlightb+average)/2*1;
+ /*
+ light.ambient[0]=0;
+ light.ambient[1]=0;
+ light.ambient[2]=0; */
+}
+
+int Game::findPathDist(int start,int end){
+ int i,j,k,smallestcount,count,connected;
+ int last,last2,last3,last4;
+ int closest;
+
+ smallestcount=1000;
+ for(i=0;i<50;i++){
+ count=0;
+ last=start;
+ last2=-1;
+ last3=-1;
+ last4=-1;
+ while(last!=end&&count<30){
+ closest=-1;
+ for(j=0;j<numpathpoints;j++){
+ if(j!=last&&j!=last2&&j!=last3&&j!=last4)
+ {
+ connected=0;
+ if(numpathpointconnect[j])
+ for(k=0;k<numpathpointconnect[j];k++){
+ if(pathpointconnect[j][k]==last)connected=1;
+ }
+ if(!connected)
+ if(numpathpointconnect[last])
+ for(k=0;k<numpathpointconnect[last];k++){
+ if(pathpointconnect[last][k]==j)connected=1;
+ }
+ if(connected)
+ if(closest==-1||Random()%2==0){
+ closest=j;
+ }
+ }
+ }
+ last4=last3;
+ last3=last2;
+ last2=last;
+ last=closest;
+ count++;
+ }
+ if(count<smallestcount)smallestcount=count;
+ }
+ return smallestcount;
+}
+
+int Game::checkcollide(XYZ startpoint,XYZ endpoint){
+ static XYZ colpoint,colviewer,coltarget;
+ static float minx,minz,maxx,maxz,miny,maxy;
+ static int i;
+
+ //startpoint.y+=.7;
+ //endpoint.y+=.7;
+ //startpoint.y-=.1;
+ //endpoint.y-=.1;
+
+ minx=startpoint.x;
+ if(minx>endpoint.x)minx=endpoint.x;
+ miny=startpoint.y;
+ if(miny>endpoint.y)miny=endpoint.y;
+ minz=startpoint.z;
+ if(minz>endpoint.z)minz=endpoint.z;
+
+ maxx=startpoint.x;
+ if(maxx<endpoint.x)maxx=endpoint.x;
+ maxy=startpoint.y;
+ if(maxy<endpoint.y)maxy=endpoint.y;
+ maxz=startpoint.z;
+ if(maxz<endpoint.z)maxz=endpoint.z;
+
+ minx-=1;
+ miny-=1;
+ minz-=1;
+ maxx+=1;
+ maxy+=1;
+ maxz+=1;
+
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.position[i].x>minx-objects.model[i].boundingsphereradius&&objects.position[i].x<maxx+objects.model[i].boundingsphereradius&&objects.position[i].y>miny-objects.model[i].boundingsphereradius&&objects.position[i].y<maxy+objects.model[i].boundingsphereradius&&objects.position[i].z>minz-objects.model[i].boundingsphereradius&&objects.position[i].z<maxz+objects.model[i].boundingsphereradius){
+ if(objects.type[i]!=treeleavestype&&objects.type[i]!=bushtype&&objects.type[i]!=firetype){
+ colviewer=startpoint;
+ coltarget=endpoint;
+ if(objects.model[i].LineCheck(&colviewer,&coltarget,&colpoint,&objects.position[i],&objects.rotation[i])!=-1)return i;
+ }
+ }
+ }
+
+ //if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
+
+ return -1;
+}
+
+int Game::checkcollide(XYZ startpoint,XYZ endpoint,int what){
+ static XYZ colpoint,colviewer,coltarget;
+ static float minx,minz,maxx,maxz,miny,maxy;
+ static int i;
+
+ //startpoint.y+=.7;
+ //endpoint.y+=.7;
+ //startpoint.y-=.1;
+ //endpoint.y-=.1;
+
+ minx=startpoint.x;
+ if(minx>endpoint.x)minx=endpoint.x;
+ miny=startpoint.y;
+ if(miny>endpoint.y)miny=endpoint.y;
+ minz=startpoint.z;
+ if(minz>endpoint.z)minz=endpoint.z;
+
+ maxx=startpoint.x;
+ if(maxx<endpoint.x)maxx=endpoint.x;
+ maxy=startpoint.y;
+ if(maxy<endpoint.y)maxy=endpoint.y;
+ maxz=startpoint.z;
+ if(maxz<endpoint.z)maxz=endpoint.z;
+
+ minx-=1;
+ miny-=1;
+ minz-=1;
+ maxx+=1;
+ maxy+=1;
+ maxz+=1;
+
+ if(what!=1000){
+ if(objects.position[what].x>minx-objects.model[what].boundingsphereradius&&objects.position[what].x<maxx+objects.model[what].boundingsphereradius&&objects.position[what].y>miny-objects.model[what].boundingsphereradius&&objects.position[what].y<maxy+objects.model[what].boundingsphereradius&&objects.position[what].z>minz-objects.model[what].boundingsphereradius&&objects.position[what].z<maxz+objects.model[what].boundingsphereradius){
+ if(objects.type[what]!=treeleavestype&&objects.type[what]!=bushtype&&objects.type[what]!=firetype){
+ colviewer=startpoint;
+ coltarget=endpoint;
+ if(objects.model[what].LineCheck(&colviewer,&coltarget,&colpoint,&objects.position[what],&objects.rotation[what])!=-1)return i;
+ }
+ }
+ }
+
+ if(what==1000)if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)return 1000;
+
+ return -1;
+}
+
+void Game::Setenvironment(int which)
+{
+ LOGFUNC;
+
+ LOG(" Setting environment...");
+
+ float temptexdetail;
+ environment=which;
+/*
+ FSOUND_SetPaused(channels[music1snow], TRUE);
+ FSOUND_SetPaused(channels[music1grass], TRUE);
+ FSOUND_SetPaused(channels[music1desert], TRUE);
+ FSOUND_SetPaused(channels[wind], TRUE);
+ FSOUND_SetPaused(channels[desertambient], TRUE);
+*/
+ FSOUND_SetPaused(channels[stream_music1snow], TRUE);
+ FSOUND_SetPaused(channels[stream_music1grass], TRUE);
+ FSOUND_SetPaused(channels[stream_music1desert], TRUE);
+ FSOUND_SetPaused(channels[stream_wind], TRUE);
+ FSOUND_SetPaused(channels[stream_desertambient], TRUE);
+
+
+ if(environment==snowyenvironment){
+ windvector=0;
+ windvector.z=3;
+ if(ambientsound){
+ //PlaySoundEx( wind, samp[wind], NULL, TRUE);
+ PlayStreamEx(stream_wind, strm[stream_wind], 0, TRUE);
+ FSOUND_SetPaused(channels[stream_wind], FALSE);
+ FSOUND_SetVolume(channels[stream_wind], 256);
+ }
+
+ LoadTexture(":Data:Textures:snowtree.png",&objects.treetextureptr,0,1);
+ LoadTexture(":Data:Textures:bushsnow.png",&objects.bushtextureptr,0,1);
+ LoadTexture(":Data:Textures:bouldersnow.jpg",&objects.rocktextureptr,1,0);
+ LoadTexture(":Data:Textures:snowbox.jpg",&objects.boxtextureptr,1,0);
+
+ FSOUND_Sample_Free(samp[footstepsound]);
+ FSOUND_Sample_Free(samp[footstepsound2]);
+ FSOUND_Sample_Free(samp[footstepsound3]);
+ FSOUND_Sample_Free(samp[footstepsound4]);
+ samp[footstepsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow2.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound3] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound4] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone2.ogg", FSOUND_HW3D, 0);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound2], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound3], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound4], 4.0f, 1000.0f);
+
+ LoadTexture(":Data:Textures:snow.jpg",&terraintexture,1,0);
+
+ LoadTexture(":Data:Textures:rock.jpg",&terraintexture2,1,0);
+
+ //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
+
+
+
+
+ temptexdetail=texdetail;
+ if(texdetail>1)texdetail=4;
+ skybox.load( ":Data:Textures:Skybox(snow):Front.jpg",
+ ":Data:Textures:Skybox(snow):Left.jpg",
+ ":Data:Textures:Skybox(snow):Back.jpg",
+ ":Data:Textures:Skybox(snow):Right.jpg",
+ ":Data:Textures:Skybox(snow):Up.jpg",
+ ":Data:Textures:Skybox(snow):Down.jpg",
+ ":Data:Textures:Skybox(snow):Cloud.jpg",
+ ":Data:Textures:Skybox(snow):Reflect.jpg");
+
+
+
+
+ texdetail=temptexdetail;
+ }
+ if(environment==desertenvironment){
+ windvector=0;
+ windvector.z=2;
+ LoadTexture(":Data:Textures:deserttree.png",&objects.treetextureptr,0,1);
+ LoadTexture(":Data:Textures:bushdesert.png",&objects.bushtextureptr,0,1);
+ LoadTexture(":Data:Textures:boulderdesert.jpg",&objects.rocktextureptr,1,0);
+ LoadTexture(":Data:Textures:desertbox.jpg",&objects.boxtextureptr,1,0);
+
+
+ if(ambientsound){
+ //PlaySoundEx( desertambient, samp[desertambient], NULL, TRUE);
+ PlayStreamEx( stream_desertambient, strm[stream_desertambient], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_desertambient], FALSE);
+ FSOUND_SetVolume(channels[stream_desertambient], 256);
+ }
+
+ FSOUND_Sample_Free(samp[footstepsound]);
+ FSOUND_Sample_Free(samp[footstepsound2]);
+ FSOUND_Sample_Free(samp[footstepsound3]);
+ FSOUND_Sample_Free(samp[footstepsound4]);
+ samp[footstepsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow2.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound3] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound4] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepsnow2.ogg", FSOUND_HW3D, 0);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound2], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound3], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound4], 4.0f, 1000.0f);
+
+ LoadTexture(":Data:Textures:sand.jpg",&terraintexture,1,0);
+
+ LoadTexture(":Data:Textures:sandslope.jpg",&terraintexture2,1,0);
+
+ //LoadTexture(":Data:Textures:detailgrain.png",&terraintexture3,1);
+
+
+
+ temptexdetail=texdetail;
+ if(texdetail>1)texdetail=4;
+ skybox.load( ":Data:Textures:Skybox(sand):Front.jpg",
+ ":Data:Textures:Skybox(sand):Left.jpg",
+ ":Data:Textures:Skybox(sand):Back.jpg",
+ ":Data:Textures:Skybox(sand):Right.jpg",
+ ":Data:Textures:Skybox(sand):Up.jpg",
+ ":Data:Textures:Skybox(sand):Down.jpg",
+ ":Data:Textures:Skybox(sand):Cloud.jpg",
+ ":Data:Textures:Skybox(sand):Reflect.jpg");
+
+
+
+
+ texdetail=temptexdetail;
+ }
+ if(environment==grassyenvironment){
+ windvector=0;
+ windvector.z=2;
+ LoadTexture(":Data:Textures:tree.png",&objects.treetextureptr,0,1);
+ LoadTexture(":Data:Textures:bush.png",&objects.bushtextureptr,0,1);
+ LoadTexture(":Data:Textures:boulder.jpg",&objects.rocktextureptr,1,0);
+ LoadTexture(":Data:Textures:grassbox.jpg",&objects.boxtextureptr,1,0);
+
+ if(ambientsound){
+ PlayStreamEx( stream_wind, strm[stream_wind], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_wind], FALSE);
+ FSOUND_SetVolume(channels[stream_wind], 100);
+ }
+
+ FSOUND_Sample_Free(samp[footstepsound]);
+ FSOUND_Sample_Free(samp[footstepsound2]);
+ FSOUND_Sample_Free(samp[footstepsound3]);
+ FSOUND_Sample_Free(samp[footstepsound4]);
+ samp[footstepsound] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepgrass1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound2] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepgrass2.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound3] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone1.ogg", FSOUND_HW3D, 0);
+ samp[footstepsound4] = FSOUND_Sample_Load(FSOUND_FREE, ":Data:Sounds:footstepstone2.ogg", FSOUND_HW3D, 0);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound2], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound3], 4.0f, 1000.0f);
+ FSOUND_Sample_SetMinMaxDistance(samp[footstepsound4], 4.0f, 1000.0f);
+
+ LoadTexture(":Data:Textures:grassdirt.jpg",&terraintexture,1,0);
+
+ LoadTexture(":Data:Textures:mossrock.jpg",&terraintexture2,1,0);
+
+ //LoadTexture(":Data:Textures:detail.png",&terraintexture3,1);
+
+
+
+ temptexdetail=texdetail;
+ if(texdetail>1)texdetail=4;
+ skybox.load( ":Data:Textures:Skybox(grass):Front.jpg",
+ ":Data:Textures:Skybox(grass):Left.jpg",
+ ":Data:Textures:Skybox(grass):Back.jpg",
+ ":Data:Textures:Skybox(grass):Right.jpg",
+ ":Data:Textures:Skybox(grass):Up.jpg",
+ ":Data:Textures:Skybox(grass):Down.jpg",
+ ":Data:Textures:Skybox(grass):Cloud.jpg",
+ ":Data:Textures:Skybox(grass):Reflect.jpg");
+
+
+
+ texdetail=temptexdetail;
+ }
+ temptexdetail=texdetail;
+ texdetail=1;
+ terrain.load(":Data:Textures:heightmap.png");
+
+ texdetail=temptexdetail;
+}
+
+
+void Game::Loadlevel(int which){
+ stealthloading=0;
+
+ if(which==0)Loadlevel((char *)":Data:Maps:map1");
+ else if(which==1)Loadlevel((char *)":Data:Maps:map2");
+ else if(which==2)Loadlevel((char *)":Data:Maps:map3");
+ else if(which==3)Loadlevel((char *)":Data:Maps:map4");
+ else if(which==4)Loadlevel((char *)":Data:Maps:map5");
+ else if(which==5)Loadlevel((char *)":Data:Maps:map6");
+ else if(which==6)Loadlevel((char *)":Data:Maps:map7");
+ else if(which==7)Loadlevel((char *)":Data:Maps:map8");
+ else if(which==8)Loadlevel((char *)":Data:Maps:map9");
+ else if(which==9)Loadlevel((char *)":Data:Maps:map10");
+ else if(which==10)Loadlevel((char *)":Data:Maps:map11");
+ else if(which==11)Loadlevel((char *)":Data:Maps:map12");
+ else if(which==12)Loadlevel((char *)":Data:Maps:map13");
+ else if(which==13)Loadlevel((char *)":Data:Maps:map14");
+ else if(which==14)Loadlevel((char *)":Data:Maps:map15");
+ else if(which==15)Loadlevel((char *)":Data:Maps:map16");
+ else if(which==-1){tutoriallevel=-1;Loadlevel((char *)":Data:Maps:tutorial");}
+ else Loadlevel((char *)":Data:Maps:mapsave");
+
+ whichlevel=which;
+}
+
+/*char * Game::MD5_string (unsigned char *string){
+char temp[50];
+char temp2[100];
+
+strcpy(temp2,(const char *)string);
+strcat((char *)temp2,(const char *)"Lugaru");
+sprintf (temp, "%d",strlen((char *)temp2));
+strcat((char *)temp2,temp);
+
+MD5 context;
+unsigned int len = strlen ( (char *)temp2);
+
+context.update ((unsigned char *)temp2, len);
+context.finalize ();
+
+return context.hex_digest();
+}*/
+
+
+
+void Game::Loadlevel(char *name){
+ int i,j,k,l,m;
+ static int oldlevel;
+ int templength;
+ float lamefloat;
+ int lameint;
+
+ float headprop,legprop,armprop,bodyprop;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading level...") + name);
+
+ if(!gameon)visibleloading=1;
+
+ if(stealthloading)visibleloading=0;
+
+ if(!stillloading)loadtime=0;
+ gamestarted=1;
+
+ numenvsounds=0;
+ //visibleloading=1;
+ if(tutoriallevel!=-1)tutoriallevel=0;
+ else tutoriallevel=1;
+
+ if(tutoriallevel==1)tutorialstage=0;
+ if(tutorialstage==0){
+ tutorialstagetime=0;
+ tutorialmaxtime=1;
+ }
+ loadingstuff=1;
+ if(!firstload){
+ oldlevel=50;
+ }
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ FSOUND_SetPaused(channels[stream_firesound], TRUE);
+
+ int mapvers;
+ FILE *tfile;
+ tfile=fopen( name, "rb" );
+ if(tfile)
+ {
+ FSOUND_SetPaused(channels[stream_firesound], TRUE);
+
+
+ scoreadded=0;
+ windialogue=0;
+
+ hostiletime=0;
+
+ won=0;
+
+ //campaign=0;
+ animation[bounceidleanim].Load((char *)":Data:Animations:Idle",middleheight,neutral);
+
+ numdialogues=0;
+
+ for(i=0;i<20;i++)
+ {
+ dialoguegonethrough[i]=0;
+ }
+
+ indialogue=-1;
+ cameramode=0;
+
+ damagedealt=0;
+ damagetaken=0;
+
+ if(accountactive!=-1)difficulty=accountdifficulty[accountactive];
+
+ if(difficulty!=2)minimap=1;
+ else minimap=0;
+
+ numhotspots=0;
+ currenthotspot=-1;
+ bonustime=1;
+
+ skyboxtexture=1;
+ skyboxr=1;
+ skyboxg=1;
+ skyboxb=1;
+
+ freeze=0;
+ winfreeze=0;
+
+ for(i=0;i<100;i++)
+ {
+ bonusnum[i]=0;
+ }
+
+ numfalls=0;
+ numflipfail=0;
+ numseen=0;
+ numstaffattack=0;
+ numswordattack=0;
+ numknifeattack=0;
+ numunarmedattack=0;
+ numescaped=0;
+ numflipped=0;
+ numwallflipped=0;
+ numthrowkill=0;
+ numafterkill=0;
+ numreversals=0;
+ numattacks=0;
+ maxalarmed=0;
+ numresponded=0;
+
+ bonustotal=startbonustotal;
+ bonus=0;
+ gameon=1;
+ changedelay=0;
+ if(console)
+ {
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ freeze=0;
+ console=0;
+ }
+
+ if(!stealthloading)
+ {
+ terrain.numdecals=0;
+ sprites.numsprites=0;
+ for(i=0;i<objects.numobjects;i++)
+ {
+ objects.model[i].numdecals=0;
+ }
+
+ j=objects.numobjects;
+ for(i=0;i<j;i++)
+ {
+ objects.DeleteObject(0);
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ }
+
+ for(i=0;i<subdivision;i++)
+ {
+ for(j=0;j<subdivision;j++)
+ {
+ terrain.patchobjectnum[i][j]=0;
+ }
+ }
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ }
+
+ weapons.numweapons=0;
+
+ funpackf(tfile, "Bi", &mapvers);
+ if(mapvers>=15)funpackf(tfile, "Bi", &indemo);
+ else indemo=0;
+ if(mapvers>=5)funpackf(tfile, "Bi", &maptype);
+ else maptype=mapkilleveryone;
+ if(mapvers>=6)funpackf(tfile, "Bi", &hostile);
+ else hostile=1;
+ if(mapvers>=4)funpackf(tfile, "Bf Bf", &viewdistance, &fadestart);
+ else
+ {
+ viewdistance=100;
+ fadestart=.6;
+ }
+ if(mapvers>=2)funpackf(tfile, "Bb Bf Bf Bf", &skyboxtexture, &skyboxr, &skyboxg, &skyboxb);
+ else
+ {
+ skyboxtexture=1;
+ skyboxr=1;
+ skyboxg=1;
+ skyboxb=1;
+ }
+ if(mapvers>=10)funpackf(tfile, "Bf Bf Bf", &skyboxlightr, &skyboxlightg, &skyboxlightb);
+ else
+ {
+ skyboxlightr=skyboxr;
+ skyboxlightg=skyboxg;
+ skyboxlightb=skyboxb;
+ }
+ if(!stealthloading)funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &player[0].coords.x,&player[0].coords.y,&player[0].coords.z,&player[0].rotation,&player[0].targetrotation, &player[0].num_weapons);
+ if(stealthloading)funpackf(tfile, "Bf Bf Bf Bf Bf Bi", &lamefloat,&lamefloat,&lamefloat,&lamefloat,&lamefloat, &player[0].num_weapons);
+ player[0].originalcoords=player[0].coords;
+ if(player[0].num_weapons>0&&player[0].num_weapons<5)
+ {
+ for(j=0;j<player[0].num_weapons;j++)
+ {
+ player[0].weaponids[j]=weapons.numweapons;
+ funpackf(tfile, "Bi", &weapons.type[weapons.numweapons]);
+ weapons.owner[weapons.numweapons]=0;
+ weapons.numweapons++;
+ }
+ }
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+
+ funpackf(tfile, "Bf Bf Bf", &player[0].armorhead, &player[0].armorhigh, &player[0].armorlow);
+ funpackf(tfile, "Bf Bf Bf", &player[0].protectionhead, &player[0].protectionhigh, &player[0].protectionlow);
+ funpackf(tfile, "Bf Bf Bf", &player[0].metalhead, &player[0].metalhigh, &player[0].metallow);
+ funpackf(tfile, "Bf Bf", &player[0].power, &player[0].speedmult);
+
+ funpackf(tfile, "Bi", &player[0].numclothes);
+
+ if(mapvers>=9)
+ {
+ funpackf(tfile, "Bi Bi", &player[0].whichskin, &player[0].creature);
+ }
+ else
+ {
+ player[0].whichskin=0;
+ player[0].creature=rabbittype;
+ }
+
+ for(i=0;i<max_dialogues;i++)
+ {
+ for(j=0;j<max_dialoguelength;j++)
+ {
+ for(k=0;k<128;k++)
+ {
+ dialoguetext[i][j][k]='\0';
+ }
+ for(k=0;k<64;k++)
+ {
+ dialoguename[i][j][k]='\0';
+ }
+ }
+ }
+
+ player[0].lastattack=-1;
+ player[0].lastattack2=-1;
+ player[0].lastattack3=-1;
+
+ if(mapvers>=8)
+ {
+ funpackf(tfile, "Bi", &numdialogues);
+ if(numdialogues)
+ {
+ for(k=0;k<numdialogues;k++)
+ {
+ funpackf(tfile, "Bi", &numdialogueboxes[k]);
+ funpackf(tfile, "Bi", &dialoguetype[k]);
+ for(l=0;l<10;l++)
+ {
+ funpackf(tfile, "Bf Bf Bf", &participantlocation[k][l].x, &participantlocation[k][l].y, &participantlocation[k][l].z);
+ funpackf(tfile, "Bf", &participantrotation[k][l]);
+ }
+ if(numdialogueboxes)
+ {
+ for(l=0;l<numdialogueboxes[k];l++)
+ {
+ funpackf(tfile, "Bi", &dialogueboxlocation[k][l]);
+ funpackf(tfile, "Bf", &dialogueboxcolor[k][l][0]);
+ funpackf(tfile, "Bf", &dialogueboxcolor[k][l][1]);
+ funpackf(tfile, "Bf", &dialogueboxcolor[k][l][2]);
+ funpackf(tfile, "Bi", &dialogueboxsound[k][l]);
+
+ bool doneread;
+
+ funpackf(tfile, "Bi",&templength);
+ if(templength>128||templength<=0)templength=128;
+ for(m=0;m<templength;m++){
+ funpackf(tfile, "Bb", &dialoguetext[k][l][m]);
+ if(dialoguetext[k][l][m]=='\0')break;
+ }
+
+ funpackf(tfile, "Bi",&templength);
+ if(templength>64||templength<=0)templength=64;
+ for(m=0;m<templength;m++){
+ funpackf(tfile, "Bb", &dialoguename[k][l][m]);
+ if(dialoguename[k][l][m]=='\0'){
+ break;
+ }
+ }
+ funpackf(tfile, "Bf Bf Bf", &dialoguecamera[k][l].x, &dialoguecamera[k][l].y, &dialoguecamera[k][l].z);
+ funpackf(tfile, "Bi", &participantfocus[k][l]);
+ funpackf(tfile, "Bi", &participantaction[k][l]);
+
+ for(m=0;m<10;m++)
+ funpackf(tfile, "Bf Bf Bf", &participantfacing[k][l][m].x, &participantfacing[k][l][m].y, &participantfacing[k][l][m].z);
+
+ funpackf(tfile, "Bf Bf",&dialoguecamerarotation[k][l],&dialoguecamerarotation2[k][l]);
+ }
+ }
+ }
+ }
+ }
+ else numdialogues=0;
+
+ if(player[0].numclothes)
+ {
+ for(k=0;k<player[0].numclothes;k++)
+ {
+ funpackf(tfile, "Bi", &templength);
+ for(l=0;l<templength;l++)
+ funpackf(tfile, "Bb", &player[0].clothes[k][l]);
+ player[0].clothes[k][templength]='\0';
+ funpackf(tfile, "Bf Bf Bf", &player[0].clothestintr[k], &player[0].clothestintg[k], &player[0].clothestintb[k]);
+ }
+ }
+
+ funpackf(tfile, "Bi", &environment);
+
+ funpackf(tfile, "Bi", &objects.numobjects);
+ if(objects.numobjects)
+ {
+ for(i=0;i<objects.numobjects;i++)
+ {
+ funpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", &objects.type[i],&objects.rotation[i],&objects.rotation2[i], &objects.position[i].x, &objects.position[i].y, &objects.position[i].z,&objects.scale[i]);
+ if(objects.type[i]==treeleavestype)objects.scale[i]=objects.scale[i-1];
+ }
+ }
+
+ if(mapvers>=7)
+ {
+ funpackf(tfile, "Bi", &numhotspots);
+ if(numhotspots)
+ {
+ for(i=0;i<numhotspots;i++)
+ {
+ funpackf(tfile, "Bi Bf Bf Bf Bf", &hotspottype[i],&hotspotsize[i],&hotspot[i].x,&hotspot[i].y,&hotspot[i].z);
+ funpackf(tfile, "Bi", &templength);
+ if(templength)
+ for(l=0;l<templength;l++)
+ funpackf(tfile, "Bb", &hotspottext[i][l]);
+ hotspottext[i][templength]='\0';
+ if(hotspottype[i]==-111)indemo=1;
+ }
+ }
+ }
+ else numhotspots=0;
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+
+ if(!stealthloading)
+ {
+ objects.center=0;
+ for(i=0;i<objects.numobjects;i++)
+ {
+ objects.center+=objects.position[i];
+ }
+ objects.center/=objects.numobjects;
+
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+
+ float maxdistance=0;
+ float tempdist;
+ int whichclosest;
+ for(i=0;i<objects.numobjects;i++)
+ {
+ tempdist=findDistancefast(&objects.center,&objects.position[i]);
+ if(tempdist>maxdistance)
+ {
+ whichclosest=i;
+ maxdistance=tempdist;
+ }
+ }
+ objects.radius=fast_sqrt(maxdistance);
+ }
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ //mapcenter=objects.center;
+ //mapradius=objects.radius;
+
+ funpackf(tfile, "Bi", &numplayers);
+ int howmanyremoved=0;
+ bool removeanother=0;
+ if(numplayers>1&&numplayers<maxplayers)
+ {
+ for(i=1;i<numplayers;i++)
+ {
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ removeanother=0;
+
+ funpackf(tfile, "Bi Bi Bf Bf Bf Bi",&player[i-howmanyremoved].whichskin,&player[i-howmanyremoved].creature, &player[i-howmanyremoved].coords.x,&player[i-howmanyremoved].coords.y,&player[i-howmanyremoved].coords.z,&player[i-howmanyremoved].num_weapons);
+ if(mapvers>=5)funpackf(tfile, "Bi", &player[i-howmanyremoved].howactive);
+ else player[i-howmanyremoved].howactive=typeactive;
+ if(mapvers>=3)funpackf(tfile, "Bf",&player[i-howmanyremoved].scale);
+ else player[i-howmanyremoved].scale=-1;
+ if(mapvers>=11)funpackf(tfile, "Bb",&player[i-howmanyremoved].immobile);
+ else player[i-howmanyremoved].immobile=0;
+ if(mapvers>=12)funpackf(tfile, "Bf",&player[i-howmanyremoved].rotation);
+ else player[i-howmanyremoved].rotation=0;
+ player[i-howmanyremoved].targetrotation=player[i-howmanyremoved].rotation;
+ if(player[i-howmanyremoved].num_weapons<0||player[i-howmanyremoved].num_weapons>5){
+ removeanother=1;
+ howmanyremoved++;
+ }
+ if(!removeanother)
+ {
+ if(player[i-howmanyremoved].num_weapons>0&&player[i-howmanyremoved].num_weapons<5)
+ {
+ for(j=0;j<player[i-howmanyremoved].num_weapons;j++)
+ {
+ player[i-howmanyremoved].weaponids[j]=weapons.numweapons;
+ funpackf(tfile, "Bi", &weapons.type[player[i-howmanyremoved].weaponids[j]]);
+ weapons.owner[player[i-howmanyremoved].weaponids[j]]=i;
+ weapons.numweapons++;
+ }
+ }
+ funpackf(tfile, "Bi", &player[i-howmanyremoved].numwaypoints);
+ //player[i-howmanyremoved].numwaypoints=10;
+ for(j=0;j<player[i-howmanyremoved].numwaypoints;j++)
+ {
+ funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].x);
+ funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].y);
+ funpackf(tfile, "Bf", &player[i-howmanyremoved].waypoints[j].z);
+ if(mapvers>=5)funpackf(tfile, "Bi", &player[i-howmanyremoved].waypointtype[j]);
+ else player[i-howmanyremoved].waypointtype[j] = wpkeepwalking;
+ }
+
+ funpackf(tfile, "Bi", &player[i-howmanyremoved].waypoint);
+ if(player[i-howmanyremoved].waypoint>player[i-howmanyremoved].numwaypoints-1)player[i-howmanyremoved].waypoint=0;
+
+ funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].armorhead, &player[i-howmanyremoved].armorhigh, &player[i-howmanyremoved].armorlow);
+ funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].protectionhead, &player[i-howmanyremoved].protectionhigh, &player[i-howmanyremoved].protectionlow);
+ funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].metalhead, &player[i-howmanyremoved].metalhigh, &player[i-howmanyremoved].metallow);
+ funpackf(tfile, "Bf Bf", &player[i-howmanyremoved].power, &player[i-howmanyremoved].speedmult);
+
+ if(mapvers>=4)funpackf(tfile, "Bf Bf Bf Bf", &headprop, &bodyprop, &armprop, &legprop);
+ else
+ {
+ headprop=1;
+ bodyprop=1;
+ armprop=1;
+ legprop=1;
+ }
+ if(player[i-howmanyremoved].creature==wolftype)
+ {
+ player[i-howmanyremoved].proportionhead=1.1*headprop;
+ player[i-howmanyremoved].proportionbody=1.1*bodyprop;
+ player[i-howmanyremoved].proportionarms=1.1*armprop;
+ player[i-howmanyremoved].proportionlegs=1.1*legprop;
+ }
+
+ if(player[i-howmanyremoved].creature==rabbittype)
+ {
+ player[i-howmanyremoved].proportionhead=1.2*headprop;
+ player[i-howmanyremoved].proportionbody=1.05*bodyprop;
+ player[i-howmanyremoved].proportionarms=1.00*armprop;
+ player[i-howmanyremoved].proportionlegs=1.1*legprop;
+ player[i-howmanyremoved].proportionlegs.y=1.05*legprop;
+ }
+
+ funpackf(tfile, "Bi", &player[i-howmanyremoved].numclothes);
+ if(player[i-howmanyremoved].numclothes)
+ {
+ for(k=0;k<player[i-howmanyremoved].numclothes;k++)
+ {
+ int templength;
+ funpackf(tfile, "Bi", &templength);
+ for(l=0;l<templength;l++)
+ funpackf(tfile, "Bb", &player[i-howmanyremoved].clothes[k][l]);
+ player[i-howmanyremoved].clothes[k][templength]='\0';
+ funpackf(tfile, "Bf Bf Bf", &player[i-howmanyremoved].clothestintr[k], &player[i-howmanyremoved].clothestintg[k], &player[i-howmanyremoved].clothestintb[k]);
+ }
+ }
+ }
+ }
+ }
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+
+ numplayers-=howmanyremoved;
+ funpackf(tfile, "Bi", &numpathpoints);
+ if(numpathpoints>30||numpathpoints<0)
+ numpathpoints=0;
+ if(numpathpoints)
+ {
+ for(j=0;j<numpathpoints;j++)
+ {
+ funpackf(tfile, "Bf Bf Bf Bi", &pathpoint[j].x,&pathpoint[j].y,&pathpoint[j].z,&numpathpointconnect[j]);
+ for(k=0;k<numpathpointconnect[j];k++){
+ funpackf(tfile, "Bi", &pathpointconnect[j][k]);
+ }
+ }
+ }
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+
+ funpackf(tfile, "Bf Bf Bf Bf", &mapcenter.x,&mapcenter.y,&mapcenter.z,&mapradius);
+
+ SetUpLighting();
+ if(environment!=oldenvironment)Setenvironment(environment);
+ oldenvironment=environment;
+
+ if(!stealthloading)
+ {
+ j=objects.numobjects;
+ objects.numobjects=0;
+ for(i=0;i<j;i++)
+ {
+ //if(objects.type[i]!=spiketype)
+ objects.MakeObject(objects.type[i],objects.position[i],objects.rotation[i],objects.rotation2[i],objects.scale[i]);
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ }
+
+ //if(skyboxtexture){
+ terrain.DoShadows();
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ objects.DoShadows();
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ /*}
+ else terrain.DoLighting();
+ */
+ }
+
+ fclose(tfile);
+
+ oldlevel=whichlevel;
+
+
+ if(numplayers>maxplayers-1)numplayers=maxplayers-1;
+ for(i=0;i<numplayers;i++)
+ {
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ player[i].burnt=0;
+ player[i].bled=0;
+ player[i].onfire=0;
+ if(i==0||player[i].scale<0)player[i].scale=.2;
+ player[i].skeleton.free=0;
+ player[i].skeleton.id=i;
+ //if(Random()%2==0)player[i].creature=wolftype;
+ //else player[i].creature=rabbittype;
+ if(i==0&&mapvers<9)player[i].creature=rabbittype;
+ if(player[i].creature!=wolftype)player[i].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",0);
+ else
+ {
+ if(player[i].creature!=wolftype){
+ player[i].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+ LoadTexture(":Data:Textures:Belt.png",&player[i].skeleton.drawmodelclothes.textureptr,1,1);
+ }
+ if(player[i].creature==wolftype){
+ player[i].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf",(char *)":Data:Skeleton:Basic Figure Wolf Low",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Wolf.solid",(char *)":Data:Models:Wolf2.solid",(char *)":Data:Models:Wolf3.solid",(char *)":Data:Models:Wolf4.solid",(char *)":Data:Models:Wolf5.solid",(char *)":Data:Models:Wolf6.solid",(char *)":Data:Models:Wolf7.solid",(char *)":Data:Models:Wolflow.solid",(char *)":Data:Models:Belt.solid",0);
+ }
+ }
+
+
+ int texsize;
+ texsize=512*512*3/texdetail/texdetail;
+ //if(!player[i].loaded)player[i].skeleton.skinText = new GLubyte[texsize];
+ //player[i].skeleton.skinText.resize(texsize);
+
+ if(player[i].creature==rabbittype)
+ {
+ if(player[i].whichskin==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==2){
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==3){
+ LoadTextureSave(":Data:Textures:Lynx.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==4){
+ LoadTextureSave(":Data:Textures:Otter.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==5){
+ LoadTextureSave(":Data:Textures:Opal.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==6){
+ LoadTextureSave(":Data:Textures:Sable.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==7){
+ LoadTextureSave(":Data:Textures:Chocolate.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==8){
+ LoadTextureSave(":Data:Textures:BW2.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==9){
+ LoadTextureSave(":Data:Textures:WB2.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ }
+ if(player[i].creature==wolftype)
+ {
+ //k=abs(Random()%3);
+ if(player[i].whichskin==0){
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==1){
+ LoadTextureSave(":Data:Textures:Darkwolf.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ else if(player[i].whichskin==2){
+ LoadTextureSave(":Data:Textures:Snowwolf.jpg",&player[i].skeleton.drawmodel.textureptr,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ }
+
+ if(player[i].numclothes)
+ {
+ for(j=0;j<player[i].numclothes;j++)
+ {
+ tintr=player[i].clothestintr[j];
+ tintg=player[i].clothestintg[j];
+ tintb=player[i].clothestintb[j];
+ AddClothes((char *)player[i].clothes[j],0,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ }
+ player[i].DoMipmaps(5,0,0,player[i].skeleton.skinsize,player[i].skeleton.skinsize);
+ }
+
+ player[i].currentanimation=bounceidleanim;
+ player[i].targetanimation=bounceidleanim;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ player[i].target=0;
+ player[i].speed=1+(float)(Random()%100)/1000;
+ if(difficulty==0)player[i].speed-=.2;
+ if(difficulty==1)player[i].speed-=.1;
+
+ player[i].velocity=0;
+ player[i].oldcoords=player[i].coords;
+ player[i].realoldcoords=player[i].coords;
+
+ player[i].id=i;
+ player[i].skeleton.id=i;
+ player[i].updatedelay=0;
+ player[i].normalsupdatedelay=0;
+
+ player[i].aitype=passivetype;
+ player[i].aitarget=0;
+ player[i].madskills=0;
+
+ if(i==0)
+ {
+ player[i].proportionhead=1.2;
+ player[i].proportionbody=1.05;
+ player[i].proportionarms=1.00;
+ player[i].proportionlegs=1.1;
+ player[i].proportionlegs.y=1.05;
+ }
+ player[i].headless=0;
+ player[i].currentoffset=0;
+ player[i].targetoffset=0;
+ /*player[i].armorhead=1;
+ player[i].armorhigh=1;
+ player[i].armorlow=1;
+ player[i].protectionhead=1;
+ player[i].protectionhigh=1;
+ player[i].protectionlow=1;
+ player[i].metalhead=1;
+ player[i].metalhigh=1;
+ player[i].metallow=1;
+ player[i].power=1;
+ player[i].speedmult=1;*/
+
+ player[i].damagetolerance=200;
+
+ if(player[i].creature==wolftype)
+ {
+ /*player[i].proportionhead=1.1;
+ player[i].proportionbody=1.1;
+ player[i].proportionarms=1.1;
+ player[i].proportionlegs=1.1;
+ player[i].proportionlegs.y=1.1;*/
+ if(i==0||player[i].scale<0)player[i].scale=.23;
+
+ player[i].damagetolerance=300;
+ }
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ if(cellophane)
+ {
+ player[i].proportionhead.z=0;
+ player[i].proportionbody.z=0;
+ player[i].proportionarms.z=0;
+ player[i].proportionlegs.z=0;
+ }
+
+ player[i].tempanimation.Load((char *)":Data:Animations:Tempanim",0,0);
+
+ player[i].headmorphness=0;
+ player[i].targetheadmorphness=1;
+ player[i].headmorphstart=0;
+ player[i].headmorphend=0;
+
+ player[i].pausetime=0;
+
+ player[i].dead=0;
+ player[i].jumppower=5;
+ player[i].damage=0;
+ player[i].permanentdamage=0;
+ player[i].superpermanentdamage=0;
+
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+
+ player[i].collided=-10;
+ player[i].loaded=1;
+ player[i].bloodloss=0;
+ player[i].weaponactive=-1;
+ player[i].weaponstuck=-1;
+ player[i].bleeding=0;
+ player[i].deathbleeding=0;
+ player[i].stunned=0;
+ player[i].hasvictim=0;
+ player[i].wentforweapon=0;
+ }
+
+ player[0].aitype=playercontrolled;
+ player[0].weaponactive=-1;
+
+ if(difficulty==1)
+ {
+ //player[0].speedmult=1/.9;
+ player[0].power=1/.9;
+ }
+
+ if(difficulty==0)
+ {
+ //player[0].speedmult=1/.8;
+ player[0].power=1/.8;
+ }
+
+ //player[0].weaponstuck=1;
+
+ if(difficulty==1)player[0].damagetolerance=250;
+ if(difficulty==0)player[0].damagetolerance=300;
+ if(difficulty==0)player[0].armorhead*=1.5;
+ if(difficulty==0)player[0].armorhigh*=1.5;
+ if(difficulty==0)player[0].armorlow*=1.5;
+ cameraloc=player[0].coords;
+ cameraloc.y+=5;
+ rotation=player[0].rotation;
+
+ hawkcoords=player[0].coords;
+ hawkcoords.y+=30;
+
+ if(visibleloading){loadscreencolor=4; LoadingScreen();}
+ //weapons.numweapons=numplayers;
+ for(i=0;i<weapons.numweapons;i++)
+ {
+ weapons.bloody[i]=0;
+ weapons.blooddrip[i]=0;
+ weapons.blooddripdelay[i]=0;
+ weapons.onfire[i]=0;
+ weapons.flamedelay[i]=0;
+ weapons.damage[i]=0;
+ //weapons.type[i]=sword;
+ if(weapons.type[i]==sword){
+ weapons.mass[i]=1.5;
+ weapons.tipmass[i]=1;
+ weapons.length[i]=.8;
+ }
+ if(weapons.type[i]==staff){
+ weapons.mass[i]=2;
+ weapons.tipmass[i]=1;
+ weapons.length[i]=1.5;
+ }
+ if(weapons.type[i]==knife){
+ weapons.mass[i]=1;
+ weapons.tipmass[i]=1.2;
+ weapons.length[i]=.25;
+ }
+ weapons.position[i]=-1000;
+ weapons.tippoint[i]=-1000;
+ }
+
+/* for(i=0;i<32;i++){
+ //if(i<16||i>20)
+ FSOUND_StopSound(i);
+ }
+*/
+ LOG("Starting background music...");
+
+ FSOUND_StopSound(FSOUND_ALL);
+ if(environment==snowyenvironment)
+ {
+ if(ambientsound)
+ {
+ PlayStreamEx(stream_wind, strm[stream_wind], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_wind], FALSE);
+ FSOUND_SetVolume(channels[stream_wind], 256);
+ }
+ }
+ else if(environment==desertenvironment)
+ {
+ if(ambientsound)
+ {
+ //PlaySoundEx(desertambient,
+ // samp[desertambient], NULL, TRUE);
+ PlayStreamEx(stream_desertambient,
+ strm[stream_desertambient], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_desertambient], FALSE);
+ FSOUND_SetVolume(channels[stream_desertambient], 256);
+ }
+ }
+ else if(environment==grassyenvironment)
+ {
+ if(ambientsound)
+ {
+ //PlaySoundEx(wind, samp[wind], NULL, TRUE);
+ PlayStreamEx(stream_wind, strm[stream_wind], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_wind], FALSE);
+ FSOUND_SetVolume(channels[stream_wind], 100);
+ }
+ }
+ oldmusicvolume[0]=0;
+ oldmusicvolume[1]=0;
+ oldmusicvolume[2]=0;
+ oldmusicvolume[3]=0;
+
+
+ /*LoadTexture(":Data:Textures:cloud.png",&sprites.cloudtexture,1,1);
+ LoadTexture(":Data:Textures:cloudimpact.png",&sprites.cloudimpacttexture,1,1);
+ LoadTexture(":Data:Textures:bloodparticle.png",&sprites.bloodtexture,1,1);
+ LoadTexture(":Data:Textures:snowflake.png",&sprites.snowflaketexture,1,1);
+ LoadTexture(":Data:Textures:flame.png",&sprites.flametexture,1,1);
+ LoadTexture(":Data:Textures:bloodflame.png",&sprites.bloodflametexture,1,1);
+ LoadTexture(":Data:Textures:smoke.png",&sprites.smoketexture,1,1);
+ LoadTexture(":Data:Textures:shine.png",&sprites.shinetexture,1,0);
+ */
+
+ if(!firstload)
+ {
+ firstload=1;
+ }
+ }
+ leveltime=0;
+ loadingstuff=0;
+ visibleloading=0;
+}
+
+void Game::Tick()
+{
+ static int i,k,j,l,m;
+ static XYZ facing,flatfacing,absflatfacing;
+ static XYZ rotatetarget;
+ static bool oldkey;
+ static float oldtargetrotation;
+ static int target, numgood;
+ static XYZ tempcoords1,tempcoords2;
+ static XYZ test;
+ static XYZ test2;
+ static XYZ lowpoint,lowpointtarget,lowpoint2,lowpointtarget2,lowpoint3,lowpointtarget3,lowpoint4,lowpointtarget4,lowpoint5,lowpointtarget5,lowpoint6,lowpointtarget6,lowpoint7,lowpointtarget7,colpoint,colpoint2;
+ static int whichhit;
+ static bool donesomething;
+ static bool oldjumpkeydown;
+
+ int templength;
+
+ float headprop,bodyprop,armprop,legprop;
+
+ if(newnetmessages){
+ newnetmessages=0;
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+
+ for(k=14;k>=2;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(k=14;k>=2;k--){
+ for(j=0;j<255;j++){
+ displaytext[k][j]=displaytext[k-1][j];
+ }
+ displaychars[k]=displaychars[k-1];
+ displaytime[k]=displaytime[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[1][j]=' ';
+ displaytext[1][j]=' ';
+ }
+ sprintf (consoletext[1], netmessages);
+ sprintf (displaytext[1], netmessages);
+ consolechars[1]=255;
+ displaychars[1]=255;
+ displaytime[1]=0;
+ }
+
+ for(i=0;i<15;i++){
+ displaytime[i]+=multiplier;
+ }
+
+ static unsigned char theKeyMap[16];
+ GetKeys( theKeyMap );
+
+ keyboardfrozen=0;
+
+
+ static bool mainmenutogglekeydown;
+ if(!console){
+ if(mainmenu&&endgame==1)mainmenu=10;
+ if(IsKeyDown(theKeyMap, MAC_ESCAPE_KEY)&&!mainmenutogglekeydown&&(mainmenu==7&&entername)){
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+ displayselected=0;
+ entername=0;
+ mainmenutogglekeydown=1;
+ }
+ if((IsKeyDown(theKeyMap, MAC_ESCAPE_KEY)||(mainmenu==0&&((IsKeyDown(theKeyMap, jumpkey)||IsKeyDown(theKeyMap, MAC_SPACE_KEY)||(campaign)))&&!oldjumpkeydown&&campaign&&winfreeze))&&!mainmenutogglekeydown&&(!mainmenu||gameon||mainmenu==3||mainmenu==4||mainmenu==5||mainmenu==6||(mainmenu==7&&!entername)||mainmenu==9||mainmenu==11||(mainmenu==12&&!tryquit)||mainmenu==13||mainmenu==14||mainmenu==15||mainmenu==16||mainmenu==17||mainmenu==10)){
+ selected=-1;
+ if(mainmenu==1||mainmenu==2||mainmenu==0){
+ if(mainmenu==0&&!winfreeze)mainmenu=2;
+ else if(mainmenu==0&&winfreeze&&(campaignchoosenext[campaignchoicewhich[whichchoice]])==1)mainmenu=100;
+ else if(mainmenu==0&&winfreeze){
+ /* if(campaignchoosenext[campaignchoicewhich[whichchoice]]==2)
+ stealthloading=1;
+ else stealthloading=0;
+
+ if(!stealthloading){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+
+ startbonustotal=0;
+
+ for(i=0;i<campaignnumlevels;i++){
+ levelvisible[i]=0;
+ levelhighlight[i]=0;
+ }
+
+ levelorder[0]=0;
+ levelvisible[0]=1;
+ if(accountcampaignchoicesmade[accountactive])
+ for(i=0;i<accountcampaignchoicesmade[accountactive];i++){
+ levelorder[i+1]=campaignnextlevel[levelorder[i]][accountcampaignchoices[accountactive][i]];
+ levelvisible[levelorder[i+1]]=1;
+ }
+ int whichlevelstart;
+ whichlevelstart=accountcampaignchoicesmade[accountactive]-1;
+ if(whichlevelstart<0){
+ campaignchoicenum=1;
+ campaignchoicewhich[0]=0;
+ }
+ else
+ {
+ campaignchoicenum=campaignnumnext[levelorder[whichlevelstart]];
+ if(campaignchoicenum)
+ for(i=0;i<campaignchoicenum;i++){
+ campaignchoicewhich[i]=campaignnextlevel[levelorder[whichlevelstart]][i];
+ levelvisible[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ levelhighlight[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ }
+ }
+
+ loading=2;
+ loadtime=0;
+ targetlevel=7;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ //else {
+ for(i=0;i<255;i++){
+ mapname[i]='\0';
+ }
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+
+ //accountcampaignchoices[accountactive][accountcampaignchoicesmade[accountactive]]=whichchoice;
+ //accountcampaignchoicesmade[accountactive]++;
+
+
+ strcat(mapname,campaignmapname[campaignchoicewhich[0]]);
+ whichchoice=0;
+ visibleloading=1;
+ stillloading=1;
+ Loadlevel(mapname);
+ campaign=1;
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[music3], TRUE);
+
+ stealthloading=0;*/
+ }
+ else if(mainmenu==1||mainmenu==2)mainmenu=0;
+ if(mainmenu&&musictoggle){
+ if(mainmenu==1||mainmenu==2||mainmenu==100){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+ FSOUND_SetPaused(channels[music1], TRUE);
+ }
+ }
+ if(!mainmenu){
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ FSOUND_SetPaused(channels[music1], FALSE);
+ }
+ }
+ if(mainmenu==3){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+
+ //ofstream opstream(":Data:config.txt");
+ ofstream opstream("./Data/config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << newscreenwidth;
+ opstream << "\nScreenheight:\n";
+ opstream << newscreenheight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << newdetail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ if(oldgamespeed==0)oldgamespeed=1;
+ opstream << oldgamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nVolume:\n";
+ opstream << volume;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(chatkey);
+ opstream.close();
+ }
+ if(mainmenu==4||mainmenu==5||mainmenu==6||mainmenu==7||mainmenu==9||mainmenu==12||mainmenu==13||mainmenu==14||mainmenu==10||mainmenu==11||mainmenu==100){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+ if(mainmenu==3&&gameon)mainmenu=2;
+ if(mainmenu==3&&!gameon)mainmenu=1;
+ if(mainmenu==5&&gameon)mainmenu=2;
+ if(mainmenu==5&&!gameon)mainmenu=1;
+ if(mainmenu==4)mainmenu=3;
+ if(mainmenu==6)mainmenu=5;
+ if(mainmenu==7)mainmenu=1;
+ if(mainmenu==9)mainmenu=5;
+ if(mainmenu==11)mainmenu=5;
+ if(mainmenu==12)mainmenu=5;
+ if(mainmenu==13)mainmenu=12;
+ if(mainmenu==14)mainmenu=13;
+ if(mainmenu==10)mainmenu=5;
+ if(mainmenu==100){
+ mainmenu=5;
+ gameon=0;
+ winfreeze=0;
+ }
+ mainmenutogglekeydown=1;
+ }
+ if(!IsKeyDown(theKeyMap, MAC_ESCAPE_KEY)){
+ mainmenutogglekeydown=0;
+ }
+ }
+
+ /*static bool minimaptogglekeydown;
+ if(IsKeyDown(theKeyMap, MAC_TAB_KEY)&&!minimaptogglekeydown){
+ minimap=1-minimap;
+ minimaptogglekeydown=1;
+ }
+ if(!IsKeyDown(theKeyMap, MAC_TAB_KEY)){
+ minimaptogglekeydown=0;
+ }
+ */
+
+ static bool minimaptogglekeydown;
+ if(IsKeyDown(theKeyMap, MAC_TAB_KEY)&&!minimaptogglekeydown&&tutoriallevel){
+ if(tutorialstage!=51)
+ tutorialstagetime=tutorialmaxtime;
+ PlaySoundEx( consolefailsound, samp[consolefailsound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolefailsound], 128);
+ FSOUND_SetPaused(channels[consolefailsound], FALSE);
+ minimaptogglekeydown=1;
+ }
+ if(!IsKeyDown(theKeyMap, MAC_TAB_KEY)){
+ minimaptogglekeydown=0;
+ }
+
+ if(mainmenu){
+ //menu buttons
+ if(mainmenu==1||mainmenu==2){
+ if(Button()&&!oldbutton&&selected==1){
+ if(!gameon){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ //new game
+ if(accountactive!=-1)mainmenu=5;
+ else mainmenu=7;
+ /*
+ startbonustotal=0;
+
+ loading=2;
+ loadtime=0;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ else {
+ Loadlevel(0);
+ }
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[music3], TRUE); */
+ }
+ else
+ {
+ //resume
+ mainmenu=0;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ FSOUND_SetPaused(channels[music1], FALSE);
+ }
+ }
+
+ if(Button()&&!oldbutton&&selected==2){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ //options
+
+ mainmenu=3;
+
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+ }
+
+ if(Button()&&!oldbutton&&selected==3){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ if(!gameon){
+ //quit
+ tryquit=1;
+ if(registered)FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+ else{
+ //end game
+ gameon=0;
+ mainmenu=1;
+ }
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+
+ if(mainmenu==3){
+ if(Button()&&!oldbutton&&selected!=-1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+ }
+ if(Button()&&!oldbutton&&selected==0){
+ int whichres;
+ whichres=-1;
+ if(newscreenwidth==640&&newscreenheight==480)whichres=0;
+ if(newscreenwidth==800&&newscreenheight==600)whichres=1;
+ if(newscreenwidth==1024&&newscreenheight==768)whichres=2;
+ if(newscreenwidth==1280&&newscreenheight==1024)whichres=3;
+ if(newscreenwidth==1600&&newscreenheight==1200)whichres=4;
+ if(newscreenwidth==840&&newscreenheight==524)whichres=5;
+ if(newscreenwidth==1024&&newscreenheight==640)whichres=6;
+ if(newscreenwidth==1344&&newscreenheight==840)whichres=7;
+
+ if(whichres==-1||whichres==7){
+ newscreenwidth=640;
+ newscreenheight=480;
+ }
+ if(whichres==0){
+ newscreenwidth=800;
+ newscreenheight=600;
+ }
+ if(whichres==1){
+ newscreenwidth=1024;
+ newscreenheight=768;
+ }
+ if(whichres==2){
+ newscreenwidth=1280;
+ newscreenheight=1024;
+ }
+ if(whichres==3){
+ newscreenwidth=1600;
+ newscreenheight=1200;
+ }
+ if(whichres==4){
+ newscreenwidth=840;
+ newscreenheight=524;
+ }
+ if(whichres==5){
+ newscreenwidth=1024;
+ newscreenheight=640;
+ }
+ if(whichres==6){
+ newscreenwidth=1344;
+ newscreenheight=840;
+ }
+ }
+ if(Button()&&!oldbutton&&selected==1){
+ newdetail++;
+ if(newdetail>2)newdetail=0;
+ }
+ if(Button()&&!oldbutton&&selected==2){
+ bloodtoggle++;
+ if(bloodtoggle>2)bloodtoggle=0;
+ }
+ if(Button()&&!oldbutton&&selected==3){
+ difficulty++;
+ if(difficulty>2)difficulty=0;
+ }
+ if(Button()&&!oldbutton&&selected==4){
+ ismotionblur=1-ismotionblur;
+ }
+ if(Button()&&!oldbutton&&selected==5){
+ decals=1-decals;
+ }
+ if(Button()&&!oldbutton&&selected==6){
+ musictoggle=1-musictoggle;
+
+ if(!musictoggle){
+ FSOUND_SetPaused(channels[music1], TRUE);
+ FSOUND_SetPaused(channels[stream_music2], TRUE);
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+
+ for(i=0;i<4;i++){
+ oldmusicvolume[i]=0;
+ musicvolume[i]=0;
+ }
+ }
+
+ if(musictoggle){
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+ }
+ }
+ if(Button()&&!oldbutton&&selected==9){
+ invertmouse=1-invertmouse;
+ }
+ if(Button()&&!oldbutton&&selected==10){
+ usermousesensitivity+=.2;
+ if(usermousesensitivity>2)usermousesensitivity=.2;
+ }
+ if(Button()&&!oldbutton&&selected==11){
+ volume+=.1f;
+ if(volume>1.0001f)volume=0;
+ FSOUND_SetSFXMasterVolume((int)(volume*255));
+ }
+ if(Button()&&!oldbutton&&selected==7){
+ /*float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+ */
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ //options
+
+ mainmenu=4;
+ keyselect=-1;
+ }
+ if(Button()&&!oldbutton&&selected==8){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+
+
+ //ofstream opstream(":Data:config.txt");
+ ofstream opstream("./Data/config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << newscreenwidth;
+ opstream << "\nScreenheight:\n";
+ opstream << newscreenheight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << newdetail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ if(oldgamespeed==0)oldgamespeed=1;
+ opstream << oldgamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nVolume:\n";
+ opstream << volume;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(chatkey);
+ opstream.close();
+
+ if(mainmenu==3&&gameon)mainmenu=2;
+ if(mainmenu==3&&!gameon)mainmenu=1;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==4){
+ if(Button()&&!oldbutton&&selected!=-1&&keyselect==-1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+ }
+ if(Button()&&!oldbutton&&selected<9&&keyselect==-1){
+ keyselect=selected;
+ oldbuttons[0]=1;
+ oldbuttons[1]=1;
+ oldbuttons[2]=1;
+ }
+ if(keyselect!=-1){
+ for(i=0;i<3;i++)
+ if(!buttons[i]&&!oldbutton&&!Button())oldbuttons[i]=0;
+ for(i=0;i<140;i++){
+ if((IsKeyDown(theKeyMap, i)||(buttons[0]&&!oldbuttons[0]&&!oldbutton)||(buttons[1]&&!oldbuttons[1]&&!oldbutton))&&keyselect!=-1){
+ if(i!=MAC_ESCAPE_KEY&&(strcmp(KeyToChar(i),"unknown")||(buttons[0]&&!oldbuttons[0]&&!oldbutton)||(buttons[1]&&!oldbuttons[1]&&!oldbutton))){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ int keynum;
+ keynum=i;
+ if(buttons[0]&&!oldbuttons[0])keynum=MAC_MOUSEBUTTON1;
+ if(buttons[1]&&!oldbuttons[1])keynum=MAC_MOUSEBUTTON2;
+
+
+
+ if(keyselect==0)forwardkey=keynum;
+ if(keyselect==1)backkey=keynum;
+ if(keyselect==2)leftkey=keynum;
+ if(keyselect==3)rightkey=keynum;
+ if(keyselect==4)crouchkey=keynum;
+ if(keyselect==5)jumpkey=keynum;
+ if(keyselect==6)drawkey=keynum;
+ if(keyselect==7)throwkey=keynum;
+ if(keyselect==8)attackkey=keynum;
+ keyselect=-1;
+ }
+ }
+ }}
+ if(Button()&&!oldbutton&&selected==9){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=3;
+
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+ }
+ }
+
+ if(mainmenu==5){
+ if(accountcampaignchoicesmade[accountactive]>8&&!registered){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+
+ gameon=0;
+ mainmenu=12;
+ accountcampaignchoicesmade[accountactive]=0;
+ accountcampaignscore[accountactive]=0;
+ accountcampaigntime[accountactive]=0;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+
+ if(endgame==2){
+ accountcampaignchoicesmade[accountactive]=0;
+ accountcampaignscore[accountactive]=0;
+ accountcampaigntime[accountactive]=0;
+ endgame=0;
+ }
+
+ if(Button()&&!oldbutton&&selected==1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ startbonustotal=0;
+
+ loading=2;
+ loadtime=0;
+ targetlevel=-1;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ else {
+ Loadlevel(-1);
+ }
+
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+ if(Button()&&!oldbutton&&selected-7>=accountcampaignchoicesmade[accountactive]){//selected>=7&&(selected-7<=campaignnumchoices)){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ startbonustotal=0;
+
+ loading=2;
+ loadtime=0;
+ targetlevel=7;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ //else {
+ for(i=0;i<255;i++){
+ mapname[i]='\0';
+ }
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+ strcat(mapname,campaignmapname[campaignchoicewhich[selected-7-accountcampaignchoicesmade[accountactive]]]);
+ whichchoice=selected-7-accountcampaignchoicesmade[accountactive];
+ visibleloading=1;
+ stillloading=1;
+ Loadlevel(mapname);
+ //Loadlevel(campaignmapname[levelorder[selected-7]]);
+ //}
+ campaign=1;
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+ if(Button()&&!oldbutton&&selected==4){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ if(mainmenu==5&&gameon)mainmenu=2;
+ if(mainmenu==5&&!gameon)mainmenu=1;
+ }
+ if(Button()&&!oldbutton&&selected==5){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=7;
+ }
+ if(Button()&&!oldbutton&&selected==3){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=6;
+ }
+ if(Button()&&!oldbutton&&selected==2){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=9;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==9){
+ if(Button()&&!oldbutton&&selected<numchallengelevels&&selected>=0&&selected<=accountprogress[accountactive]){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ startbonustotal=0;
+
+ loading=2;
+ loadtime=0;
+ targetlevel=selected;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ else {
+ Loadlevel(selected);
+ }
+ campaign=0;
+
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+ if(Button()&&!oldbutton&&selected==numchallengelevels){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=5;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==11){
+ if(Button()&&!oldbutton&&selected<numchallengelevels&&selected>=0&&selected<=accountprogress[accountactive]){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ startbonustotal=0;
+
+ loading=2;
+ loadtime=0;
+ targetlevel=selected;
+ if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ else {
+ Loadlevel(selected);
+ }
+ campaign=0;
+
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+ if(Button()&&!oldbutton&&selected==numchallengelevels){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=5;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==10){
+ endgame=2;
+ if(Button()&&!oldbutton&&selected==3){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=5;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+
+ if(mainmenu==15||mainmenu==16){
+ if(Button()&&!oldbutton&&selected==1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ if(mainmenu==15)mainmenu=5;
+ else mainmenu=12;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+
+ if(mainmenu==12){
+ endgame=2;
+ if(Button()&&!oldbutton&&selected==3){
+ if(tryquit)quit=1;
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=5;
+ }
+
+ if(Button()&&!oldbutton&&selected==4){
+ registernow=1;
+ quit=1;
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+
+
+ if(Button()&&!oldbutton&&selected==5){
+ tryquit=0;
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=13;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==6){
+ if(Button()&&!oldbutton&&selected!=-1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+ }
+ if(Button()&&!oldbutton&&selected==1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ for(i=accountactive;i<numaccounts-1;i++){
+ accountdifficulty[i]=accountdifficulty[i+1];
+ accountcampaignchoicesmade[i]=accountcampaignchoicesmade[i+1];
+ for(j=0;j<accountcampaignchoicesmade[i+1];j++){
+ accountcampaignchoices[i][j]=accountcampaignchoices[i+1][j];
+ }
+ accountpoints[i]=accountpoints[i+1];
+ for(j=0;j<50;j++){
+ accounthighscore[i][j]=accounthighscore[i+1][j];
+ accountfasttime[i][j]=accountfasttime[i+1][j];
+ }
+ for(j=0;j<60;j++){
+ accountunlocked[i][j]=accountunlocked[i+1][j];
+ }
+ for(j=0;j<256;j++){
+ accountname[i][j]=accountname[i+1][j];
+ }
+ accountcampaignhighscore[i]=accountcampaignhighscore[i+1];
+ accountprogress[i]=accountprogress[i+1];
+ accountcampaignfasttime[i]=accountcampaignfasttime[i+1];
+ accountcampaignscore[i]=accountcampaignscore[i+1];
+ accountcampaigntime[i]=accountcampaigntime[i+1];
+ }
+
+ numaccounts--;
+ accountactive=-1;
+
+
+ mainmenu=7;
+ }
+ if(Button()&&!oldbutton&&selected==2){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=5;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==7){
+ if(Button()&&!oldbutton&&selected!=-1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+ }
+ if(Button()&&!oldbutton&&selected==0&&numaccounts<8){
+ entername=1;
+ }
+ if(Button()&&!oldbutton&&selected>0&&selected<numaccounts+1){
+ accountactive=selected-1;
+ mainmenu=5;
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+ if(Button()&&!oldbutton&&selected==numaccounts+1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ mainmenu=1;
+
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+ displayselected=0;
+ entername=0;
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+ if(mainmenu==8){
+ if(Button()&&!oldbutton&&selected!=-1){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ if(selected==0)accountdifficulty[accountactive]=0;
+ if(selected==1)accountdifficulty[accountactive]=1;
+ if(selected==2)accountdifficulty[accountactive]=2;
+
+ mainmenu=5;
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ }
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+ }
+
+
+ if(Button())oldbutton=1;
+ else oldbutton=0;
+
+ if(IsKeyDown(theKeyMap, MAC_Q_KEY)&&IsKeyDown(theKeyMap, MAC_COMMAND_KEY)){
+ tryquit=1;
+ if(mainmenu==3){
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+
+ //ofstream opstream(":Data:config.txt");
+ ofstream opstream("./Data/config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << newscreenwidth;
+ opstream << "\nScreenheight:\n";
+ opstream << newscreenheight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << newdetail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ if(oldgamespeed==0)oldgamespeed=1;
+ opstream << oldgamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nVolume:\n";
+ opstream << volume;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(chatkey);
+ opstream.close();
+ }
+ }
+
+ if(mainmenu==1||mainmenu==2){
+ if(loaddistrib>4)transition+=multiplier/8;
+ if(transition>1){
+ transition=0;
+ anim++;
+ if(anim>4)anim=0;
+ loaddistrib=0;
+ }
+ }
+ FSOUND_SetFrequency(channels[stream_music3], 22050);
+
+ if(entername||mainmenu==13||mainmenu==14){
+ for(i=0;i<140;i++){
+ if(IsKeyDown(theKeyMap, i)){
+ togglekeydelay[i]+=multiplier;
+ if(togglekeydelay[i]>.4){
+ togglekey[i]=0;
+ togglekeydelay[i]=.36;
+ }
+ if(!togglekey[i]){
+ if(KeyToSingleChar(i)!='\0'&&displaychars[0]<60){
+ for(j=255;j>=displayselected+1;j--){
+ displaytext[0][j]=displaytext[0][j-1];
+ }
+ displaytext[0][displayselected]=KeyToSingleChar(i);
+ if(IsKeyDown(theKeyMap, MAC_SHIFT_KEY))displaytext[0][displayselected]=Shift(displaytext[0][displayselected]);
+ displayselected++;
+ displaychars[0]++;
+ }
+ if(i==MAC_DELETE_KEY&&displayselected!=0){
+ for(j=displayselected-1;j<255;j++){
+ displaytext[0][j]=displaytext[0][j+1];
+ }
+ displaytext[0][255]=' ';
+ displayselected--;
+ displaychars[0]--;
+ }
+ if(i==MAC_ARROW_LEFT_KEY&&displayselected!=0){
+ displayselected--;
+ }
+ if(i==MAC_ARROW_RIGHT_KEY&&displayselected<displaychars[0]){
+ displayselected++;
+ }
+ if(i==MAC_RETURN_KEY&&entername){
+ if(displaychars[0]){
+ numaccounts++;
+ strcpy(accountname[numaccounts-1],displaytext[0]);
+ accountactive=numaccounts-1;
+ accountdifficulty[accountactive]=1;
+ accountprogress[accountactive]=0;
+ accountpoints[accountactive]=0;
+ accountcampaigntime[accountactive]=0;
+ accountcampaignscore[accountactive]=0;
+ accountcampaignfasttime[accountactive]=0;
+ accountcampaignhighscore[accountactive]=0;
+ for(j=0;j<50;j++){
+ accounthighscore[accountactive][j]=0;
+ accountfasttime[accountactive][j]=0;
+ }
+ for(j=0;j<60;j++){
+ accountunlocked[accountactive][j]=0;
+ }
+ accountcampaignchoicesmade[accountactive]=0;
+
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+ displayselected=0;
+ entername=0;
+
+ mainmenu=8;
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+
+
+ displayselected=0;
+ }}
+
+ if(i==MAC_RETURN_KEY&&mainmenu==14){
+ if(displaychars[0]){
+ char serialstring[256];
+ char tempstring[256];
+ sprintf (tempstring, "%s-windows", registrationname);
+ long num1;
+ long num2;
+ long num3;
+ long num4;
+ long long longnum;
+ longnum = MD5_string ( tempstring);
+ //longnum = 1111111111111111;
+ num1 = longnum/100000000;
+ num2 = longnum%100000000;
+ sprintf (tempstring, "%d-%d-%d-%d\0\0\0\0\0", num1/10000, num1%10000, num2/10000, num2%10000);
+
+ int goodcode=3;
+ int numchars=3;
+ if(num1/10000>999)numchars+=4;
+ else if(num1/10000>99)numchars+=3;
+ else if(num1/10000>9)numchars+=2;
+ else numchars+=1;
+ if(num1%10000>999)numchars+=4;
+ else if(num1%10000>99)numchars+=3;
+ else if(num1%10000>9)numchars+=2;
+ else numchars+=1;
+ if(num2/10000>999)numchars+=4;
+ else if(num2/10000>99)numchars+=3;
+ else if(num2/10000>9)numchars+=2;
+ else numchars+=1;
+ if(num2%10000>999)numchars+=4;
+ else if(num2%10000>99)numchars+=3;
+ else if(num2%10000>9)numchars+=2;
+ else numchars+=1;
+
+ //numchars=12;
+
+ for(j=0;j<numchars;j++){
+ if(displaytext[0][j]!=tempstring[j]&&tempstring[j]!=' '&&tempstring[j]!='\0')goodcode--;
+ }
+
+ if(longnum==5077041556214789)goodcode=-1;
+
+ if(goodcode<0)goodcode=0;
+
+ if(goodcode){
+ registered=1;
+ mainmenu=15;
+
+ FILE *tfile;
+ tfile=fopen( ":Data:Sounds:flame.ogg", "wb" );
+ if (tfile)
+ {
+ int numchars;
+ numchars=strlen(registrationname);
+ fpackf(tfile, "Bb", registered);
+ fpackf(tfile, "Bi", numchars);
+ if(numchars>0)
+ {
+ for(j=0;j<numchars;j++)
+ {
+ fpackf(tfile, "Bb", registrationname[j]);
+ }
+ }
+ fpackf(tfile, "Bi", num1);
+ fpackf(tfile, "Bi", num2);
+ fclose(tfile);
+ }
+ }
+ else
+ {
+ mainmenu=16;
+ }
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+ displayselected=0;
+ }}
+
+ if(i==MAC_RETURN_KEY&&mainmenu==13){
+ if(displaychars[0]){
+ sprintf (registrationname, "%s", displaytext[0]);
+ if(displaychars[0]<254)registrationname[displaychars[0]]='\0';
+
+ mainmenu=14;
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+
+ /*char tempstring[50];
+ sprintf (tempstring, registrationname);
+ long num1;
+ long num2;
+ long num3;
+ long num4;
+ long long longnum;
+ longnum = MD5_string ( tempstring);
+ num1 = longnum/100000000;
+ num2 = longnum%100000000;
+ sprintf (displaytext[0], "%d-%d-%d-%d", num1/10000, num1%10000, num2/10000, num2%10000);
+
+ displaychars[0]=strlen(displaytext[0]);
+ */
+ displayselected=0;
+ }}
+ }
+ togglekey[i]=1;
+ }
+ else {
+ togglekey[i]=0;
+ togglekeydelay[i]=0;
+ }
+ }
+
+ displayblinkdelay-=multiplier;
+ if(displayblinkdelay<=0){
+ displayblinkdelay=.3;
+ displayblink=1-displayblink;
+ }
+ }
+ }
+
+ if(!mainmenu){
+ if(hostile==1)hostiletime+=multiplier;
+ else hostiletime=0;
+ if(!winfreeze)leveltime+=multiplier;
+ if(IsKeyDown(theKeyMap, MAC_ESCAPE_KEY)){
+ chatting=0;
+ console=0;
+ freeze=0;
+ displaychars[0]=0;
+ }
+
+ if(IsKeyDown(theKeyMap, chatkey)&&!chattogglekeydown&&!console&&!chatting&&debugmode){
+ chatting=1;
+ chattogglekeydown=1;
+ togglekey[chatkey]=1;
+ togglekeydelay[chatkey]=-20;
+ }
+
+ if(!IsKeyDown(theKeyMap, chatkey)){
+ chattogglekeydown=0;
+ }
+
+ if(chatting){
+ for(i=0;i<140;i++){
+ if(IsKeyDown(theKeyMap, i)){
+ togglekeydelay[i]+=multiplier;
+ if(togglekeydelay[i]>.4){
+ togglekey[i]=0;
+ togglekeydelay[i]=.36;
+ }
+ if(!togglekey[i]){
+ if(KeyToSingleChar(i)!='\0'&&displaychars[0]<60){
+ for(j=255;j>=displayselected+1;j--){
+ displaytext[0][j]=displaytext[0][j-1];
+ }
+ displaytext[0][displayselected]=KeyToSingleChar(i);
+ if(IsKeyDown(theKeyMap, MAC_SHIFT_KEY))displaytext[0][displayselected]=Shift(displaytext[0][displayselected]);
+ displayselected++;
+ displaychars[0]++;
+ }
+ if(i==MAC_DELETE_KEY&&displayselected!=0){
+ for(j=displayselected-1;j<255;j++){
+ displaytext[0][j]=displaytext[0][j+1];
+ }
+ displaytext[0][255]=' ';
+ displayselected--;
+ displaychars[0]--;
+ }
+ if(i==MAC_ARROW_LEFT_KEY&&displayselected!=0){
+ displayselected--;
+ }
+ if(i==MAC_ARROW_RIGHT_KEY&&displayselected<displaychars[0]){
+ displayselected++;
+ }
+ if(i==MAC_RETURN_KEY){
+ if(displaychars[0]){
+ /*for(j=0;j<displaychars[0];j++){
+ talkname[j]=displaytext[0][j];
+ }
+ talkname[displaychars[0]]='\0';
+ sprintf (chatname, "%s: %s",playerName,talkname);
+ //NetworkSendInformation(chatname);
+ */
+ for(j=0;j<255;j++){
+ displaytext[0][j]=' ';
+ }
+ displaychars[0]=0;
+ displayselected=0;
+ chatting=0;
+ }
+ }
+ }
+ togglekey[i]=1;
+ }
+ else {
+ togglekey[i]=0;
+ togglekeydelay[i]=0;
+ }
+ }
+
+ displayblinkdelay-=multiplier;
+ if(displayblinkdelay<=0){
+ displayblinkdelay=.3;
+ displayblink=1-displayblink;
+ }
+ }
+
+ if(chatting)keyboardfrozen=1;
+
+ if(IsKeyDown(theKeyMap, MAC_V_KEY)&&!freezetogglekeydown&&debugmode){
+ freeze=1-freeze;
+ if(freeze){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ }
+ freezetogglekeydown=1;
+ }
+
+ if(!IsKeyDown(theKeyMap, MAC_V_KEY)&&!IsKeyDown(theKeyMap, MAC_F1_KEY)){
+ freezetogglekeydown=0;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_TILDE_KEY)&&!consoletogglekeydown&&debugmode){
+ console=1-console;
+ if(!console)freeze=0;
+ if(console){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ }
+ consoletogglekeydown=1;
+ }
+
+ if(!IsKeyDown(theKeyMap, MAC_TILDE_KEY)){
+ consoletogglekeydown=0;
+ }
+
+ if(console)freeze=1;
+
+ if(console&&!IsKeyDown(theKeyMap,MAC_COMMAND_KEY)){
+ for(i=0;i<140;i++){
+ if(IsKeyDown(theKeyMap, i)){
+ togglekeydelay[i]+=multiplier;
+ if(togglekeydelay[i]>.4){
+ togglekey[i]=0;
+ togglekeydelay[i]=.36;
+ }
+ if(!togglekey[i]){
+ if(KeyToSingleChar(i)!='\0'&&consolechars[0]<255){
+ for(j=255;j>=consoleselected+1;j--){
+ consoletext[0][j]=consoletext[0][j-1];
+ }
+ consoletext[0][consoleselected]=KeyToSingleChar(i);
+ if(IsKeyDown(theKeyMap, MAC_SHIFT_KEY))consoletext[0][consoleselected]=Shift(consoletext[0][consoleselected]);
+ consoleselected++;
+ consolechars[0]++;
+ }
+ else if(i==MAC_ENTER_KEY){
+ for(j=255;j>=consoleselected+1;j--){
+ consoletext[0][j]=consoletext[0][j-1];
+ }
+ consoletext[0][consoleselected]='\n';
+ consoleselected++;
+ consolechars[0]++;
+ }
+ if(i==MAC_DELETE_KEY&&consoleselected!=0){
+ for(j=consoleselected-1;j<255;j++){
+ consoletext[0][j]=consoletext[0][j+1];
+ }
+ consoletext[0][255]=' ';
+ consoleselected--;
+ consolechars[0]--;
+ }
+ if(i==MAC_ARROW_UP_KEY){
+ if(archiveselected<14)archiveselected++;
+ for(j=0;j<255;j++){
+ consolechars[0]=consolechars[archiveselected];
+ consoletext[0][j]=consoletext[archiveselected][j];
+ consoleselected=consolechars[0];
+ }
+ }
+ if(i==MAC_ARROW_DOWN_KEY){
+ if(archiveselected>0)archiveselected--;
+ for(j=0;j<255;j++){
+ consolechars[0]=consolechars[archiveselected];
+ consoletext[0][j]=consoletext[archiveselected][j];
+ consoleselected=consolechars[0];
+ }
+ }
+ if(i==MAC_ARROW_LEFT_KEY&&consoleselected!=0){
+ consoleselected--;
+ }
+ if(i==MAC_ARROW_RIGHT_KEY&&consoleselected<consolechars[0]){
+ consoleselected++;
+ }
+ if(i==MAC_RETURN_KEY){
+ archiveselected=0;
+ donesomething=0;
+ if(Compare(consoletext[0],"quit ",0,4)||Compare(consoletext[0],"exit ",0,4)){
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ donesomething=1;
+ tryquit=1;
+ }
+ /*if(Compare(consoletext[0],"send ",0,4)){
+ for(j=5;j<consolechars[0];j++){
+ talkname[j-5]=consoletext[0][j];
+ }
+ talkname[consolechars[0]-5]='\0';
+ sprintf (chatname, "%s: %s",playerName,talkname);
+ //NetworkSendInformation(chatname);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"name ",0,4)){
+ int numchars;
+ numchars=consolechars[0]-5;
+ if(numchars>32)numchars=32;
+ for(j=5;j<numchars+5;j++){
+ talkname[j-5]=consoletext[0][j];
+ }
+ talkname[numchars]='\0';
+ sprintf (chatname, "Player %s is now known as %s.",playerName,talkname);
+ //NetworkSendInformation(chatname);
+ sprintf (playerName, "%s",talkname);
+ //NetworkSendName(playerName);
+ donesomething=1;
+ }*/
+ if(Compare(consoletext[0],"map ",0,3)){
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+ for(j=4;j<consolechars[0];j++){
+ mapname[j-4+11]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-4+11]='\0';
+ Loadlevel(mapname);
+ whichlevel=-2;
+ campaign=0;
+ donesomething=1;
+ }
+ /*if(Compare(consoletext[0],"connect ",0,7)&&!ishost){
+ int v;
+ unsigned char playerNameStr[32];
+ char theIPAddress[256];
+ char thePort[32];
+ NMUInt32 port = 25710;
+
+ strcpy(playerName, "Client");
+ GameC2PStr( playerName, playerNameStr );
+
+ for(j=0;j<consolechars[0]-8;j++){
+ theIPAddress[j]=consoletext[0][j+8];
+ }
+ theIPAddress[consolechars[0]-8]='\0';
+
+ sprintf( thePort, "%li", port );
+ v=NetworkStartClient( theIPAddress, thePort, playerNameStr );
+ if(v)
+ {
+ if(consolechars[0]>0){
+ for(k=14;k>=1;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[0][j]=' ';
+ }
+ if(v!=-4994)sprintf (consoletext[0], "Error #%d!!!",v);
+ else sprintf (consoletext[0], "Could not open connection");
+
+ consolechars[0]=255;
+ consoleselected=0;
+ }
+ }
+ else
+ {
+ donesomething=1;
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+
+ if(consolechars[0]>0){
+ for(k=14;k>=1;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[0][j]=' ';
+ }
+ sprintf (consoletext[0], "Connected to %s",theIPAddress);
+
+ consolechars[0]=255;
+ consoleselected=0;
+ }
+ }
+ }
+
+ if(Compare(consoletext[0],"host ",0,4)){
+ unsigned char gameNameStr[32], playerNameStr[32];
+ char gameName[32];//, playerName[32];
+ NMUInt32 port;
+ int players;
+ int v;
+
+ port = 25710;
+ players =4;
+
+ strcpy(gameName, "Host's game");
+ strcpy(playerName, "Host");
+ GameC2PStr( gameName, gameNameStr );
+ GameC2PStr( playerName, playerNameStr );
+
+ v=NetworkStartServer( (NMUInt16)port, players, gameNameStr, playerNameStr );
+ if(v)
+ {
+ if(consolechars[0]>0){
+ for(k=14;k>=1;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[0][j]=' ';
+ }
+ sprintf (consoletext[0], "Error #%d!!!",v);
+
+ consolechars[0]=255;
+ consoleselected=0;
+ }
+ }
+ else
+ {
+ donesomething=1;
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+
+ if(consolechars[0]>0){
+ for(k=14;k>=1;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[0][j]=' ';
+ }
+ sprintf (consoletext[0], "Game hosted");
+
+ consolechars[0]=255;
+ consoleselected=0;
+ }
+ }
+ }
+ */
+ if(Compare(consoletext[0],"save ",0,4)){
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+ for(j=5;j<consolechars[0];j++){
+ mapname[j-5+11]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-5+11]='\0';
+
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+
+ int mapvers;
+ mapvers=12;
+
+
+ FILE *tfile;
+ tfile=fopen( mapname, "wb" );
+ fpackf(tfile, "Bi", mapvers);
+ //fpackf(tfile, "Bi", indemo);
+ fpackf(tfile, "Bi", maptype);
+ fpackf(tfile, "Bi", hostile);
+ fpackf(tfile, "Bf Bf", viewdistance, fadestart);
+ fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
+ fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
+ fpackf(tfile, "Bf Bf Bf Bf Bf Bi", player[0].coords.x, player[0].coords.y, player[0].coords.z, player[0].rotation, player[0].targetrotation, player[0].num_weapons);
+ if(player[0].num_weapons>0&&player[0].num_weapons<5)
+ for(j=0;j<player[0].num_weapons;j++){
+ fpackf(tfile, "Bi", weapons.type[player[0].weaponids[j]]);
+ }
+
+ fpackf(tfile, "Bf Bf Bf", player[0].armorhead, player[0].armorhigh, player[0].armorlow);
+ fpackf(tfile, "Bf Bf Bf", player[0].protectionhead, player[0].protectionhigh, player[0].protectionlow);
+ fpackf(tfile, "Bf Bf Bf", player[0].metalhead, player[0].metalhigh, player[0].metallow);
+ fpackf(tfile, "Bf Bf", player[0].power, player[0].speedmult);
+
+ fpackf(tfile, "Bi", player[0].numclothes);
+
+ fpackf(tfile, "Bi Bi", player[0].whichskin, player[0].creature);
+
+ fpackf(tfile, "Bi", numdialogues);
+ if(numdialogues)
+ for(k=0;k<numdialogues;k++){
+ fpackf(tfile, "Bi", numdialogueboxes[k]);
+ fpackf(tfile, "Bi", dialoguetype[k]);
+ for(l=0;l<10;l++){
+ fpackf(tfile, "Bf Bf Bf", participantlocation[k][l].x, participantlocation[k][l].y, participantlocation[k][l].z);
+ fpackf(tfile, "Bf", participantrotation[k][l]);
+ }
+ if(numdialogueboxes)
+ for(l=0;l<numdialogueboxes[k];l++){
+ fpackf(tfile, "Bi", dialogueboxlocation[k][l]);
+ fpackf(tfile, "Bf", dialogueboxcolor[k][l][0]);
+ fpackf(tfile, "Bf", dialogueboxcolor[k][l][1]);
+ fpackf(tfile, "Bf", dialogueboxcolor[k][l][2]);
+ fpackf(tfile, "Bi", dialogueboxsound[k][l]);
+
+ templength=strlen(dialoguetext[k][l]);
+ fpackf(tfile, "Bi",(templength));
+ for(m=0;m<templength;m++){
+ fpackf(tfile, "Bb", dialoguetext[k][l][m]);
+ if(dialoguetext[k][l][m]=='\0')break;
+ }
+
+ templength=strlen(dialoguename[k][l]);
+ fpackf(tfile, "Bi",templength);
+ for(m=0;m<templength;m++){
+ fpackf(tfile, "Bb", dialoguename[k][l][m]);
+ if(dialoguename[k][l][m]=='\0')break;
+ }
+
+ fpackf(tfile, "Bf Bf Bf", dialoguecamera[k][l].x, dialoguecamera[k][l].y, dialoguecamera[k][l].z);
+ fpackf(tfile, "Bi", participantfocus[k][l]);
+ fpackf(tfile, "Bi", participantaction[k][l]);
+
+ for(m=0;m<10;m++)
+ fpackf(tfile, "Bf Bf Bf", participantfacing[k][l][m].x, participantfacing[k][l][m].y, participantfacing[k][l][m].z);
+
+ fpackf(tfile, "Bf Bf",dialoguecamerarotation[k][l],dialoguecamerarotation2[k][l]);
+ }
+ }
+
+ if(player[0].numclothes)
+ for(k=0;k<player[0].numclothes;k++){
+ templength=strlen(player[0].clothes[k]);
+ fpackf(tfile, "Bi", templength);
+ for(l=0;l<templength;l++)
+ fpackf(tfile, "Bb", player[0].clothes[k][l]);
+ fpackf(tfile, "Bf Bf Bf", player[0].clothestintr[k], player[0].clothestintg[k], player[0].clothestintb[k]);
+ }
+
+ fpackf(tfile, "Bi", environment);
+
+ fpackf(tfile, "Bi", objects.numobjects);
+
+ if(objects.numobjects)
+ for(k=0;k<objects.numobjects;k++){
+ fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", objects.type[k], objects.rotation[k], objects.rotation2[k], objects.position[k].x, objects.position[k].y, objects.position[k].z, objects.scale[k]);
+ }
+
+ fpackf(tfile, "Bi", numhotspots);
+ if(numhotspots)
+ for(i=0;i<numhotspots;i++){
+ fpackf(tfile, "Bi Bf Bf Bf Bf", hotspottype[i],hotspotsize[i],hotspot[i].x,hotspot[i].y,hotspot[i].z);
+ templength=strlen(hotspottext[i]);
+ fpackf(tfile, "Bi",templength);
+ for(l=0;l<templength;l++)
+ fpackf(tfile, "Bb", hotspottext[i][l]);
+ }
+
+ fpackf(tfile, "Bi", numplayers);
+ if(numplayers>1&&numplayers<maxplayers)
+ for(j=1;j<numplayers;j++){
+ fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", player[j].whichskin, player[j].creature, player[j].coords.x, player[j].coords.y, player[j].coords.z, player[j].num_weapons, player[j].howactive, player[j].scale, player[j].immobile, player[j].rotation);
+ if(player[j].num_weapons>0&&player[j].num_weapons<5)
+ for(k=0;k<player[j].num_weapons;k++){
+ fpackf(tfile, "Bi", weapons.type[player[j].weaponids[k]]);
+ }
+ if(player[j].numwaypoints<30){
+ fpackf(tfile, "Bi", player[j].numwaypoints);
+ for(k=0;k<player[j].numwaypoints;k++){
+ fpackf(tfile, "Bf", player[j].waypoints[k].x);
+ fpackf(tfile, "Bf", player[j].waypoints[k].y);
+ fpackf(tfile, "Bf", player[j].waypoints[k].z);
+ fpackf(tfile, "Bi", player[j].waypointtype[k]);
+ }
+ fpackf(tfile, "Bi", player[j].waypoint);
+ }
+ else{
+ player[j].numwaypoints=0;
+ player[j].waypoint=0;
+ fpackf(tfile, "Bi Bi Bi", player[j].numwaypoints, player[j].waypoint, player[j].waypoint);
+ }
+
+ fpackf(tfile, "Bf Bf Bf", player[j].armorhead, player[j].armorhigh, player[j].armorlow);
+ fpackf(tfile, "Bf Bf Bf", player[j].protectionhead, player[j].protectionhigh, player[j].protectionlow);
+ fpackf(tfile, "Bf Bf Bf", player[j].metalhead, player[j].metalhigh, player[j].metallow);
+ fpackf(tfile, "Bf Bf", player[j].power, player[j].speedmult);
+
+ if(player[j].creature==wolftype){
+ headprop=player[j].proportionhead.x/1.1;
+ bodyprop=player[j].proportionbody.x/1.1;
+ armprop=player[j].proportionarms.x/1.1;
+ legprop=player[j].proportionlegs.x/1.1;
+ }
+
+ if(player[j].creature==rabbittype){
+ headprop=player[j].proportionhead.x/1.2;
+ bodyprop=player[j].proportionbody.x/1.05;
+ armprop=player[j].proportionarms.x/1.00;
+ legprop=player[j].proportionlegs.x/1.1;
+ }
+
+ fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
+
+
+
+ fpackf(tfile, "Bi", player[j].numclothes);
+ if(player[j].numclothes)
+ for(k=0;k<player[j].numclothes;k++){
+ int templength;
+ templength=strlen(player[j].clothes[k]);
+ fpackf(tfile, "Bi", templength);
+ for(l=0;l<templength;l++)
+ fpackf(tfile, "Bb", player[j].clothes[k][l]);
+ fpackf(tfile, "Bf Bf Bf", player[j].clothestintr[k], player[j].clothestintg[k], player[j].clothestintb[k]);
+ }
+ }
+
+ fpackf(tfile, "Bi", numpathpoints);
+ if(numpathpoints)
+ for(j=0;j<numpathpoints;j++){
+ fpackf(tfile, "Bf Bf Bf Bi", pathpoint[j].x, pathpoint[j].y, pathpoint[j].z, numpathpointconnect[j]);
+ for(k=0;k<numpathpointconnect[j];k++){
+ fpackf(tfile, "Bi", pathpointconnect[j][k]);
+ }
+ }
+
+ fpackf(tfile, "Bf Bf Bf Bf", mapcenter.x, mapcenter.y, mapcenter.z, mapradius);
+
+
+ fclose(tfile);
+ donesomething=1;
+
+ /*
+ FILE *tfile;
+ tfile=fopen( mapname, "wb" );
+ fwrite( &mapvers, 1, sizeof(int), tfile );
+ fwrite( &player[0].coords.x, 1, sizeof(float), tfile );
+ fwrite( &player[0].coords.y, 1, sizeof(float), tfile );
+ fwrite( &player[0].coords.z, 1, sizeof(float), tfile );
+ fwrite( &player[0].rotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].targetrotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].num_weapons, 1, sizeof(int), tfile );
+ if(player[0].num_weapons>0&&player[0].num_weapons<5)
+ for(j=0;j<player[0].num_weapons;j++){
+ fwrite( &weapons.type[player[0].weaponids[j]], 1, sizeof(int), tfile );
+ }
+
+ fwrite( &player[0].armorhead, 1, sizeof(int), tfile );
+ fwrite( &player[0].armorhigh, 1, sizeof(int), tfile );
+ fwrite( &player[0].armorlow, 1, sizeof(int), tfile );
+ fwrite( &player[0].protectionhead, 1, sizeof(int), tfile );
+ fwrite( &player[0].protectionhigh, 1, sizeof(int), tfile );
+ fwrite( &player[0].protectionlow, 1, sizeof(int), tfile );
+ fwrite( &player[0].metalhead, 1, sizeof(int), tfile );
+ fwrite( &player[0].metalhigh, 1, sizeof(int), tfile );
+ fwrite( &player[0].metallow, 1, sizeof(int), tfile );
+ fwrite( &player[0].power, 1, sizeof(int), tfile );
+ fwrite( &player[0].speedmult, 1, sizeof(int), tfile );
+
+ fwrite( &player[0].numclothes, 1, sizeof(int), tfile );
+ if(player[0].numclothes)
+ for(k=0;k<player[0].numclothes;k++){
+ int templength;
+ templength=strlen(player[0].clothes[k]);
+ fwrite( &templength,1,sizeof(int),tfile);
+ for(l=0;l<templength;l++)
+ fwrite( &player[0].clothes[k][l],1,sizeof(char),tfile);
+ fwrite( &player[0].clothestintr[k],1,sizeof(float),tfile);
+ fwrite( &player[0].clothestintg[k],1,sizeof(float),tfile);
+ fwrite( &player[0].clothestintb[k],1,sizeof(float),tfile);
+ }
+
+ fwrite( &environment, 1, sizeof(int), tfile );
+
+ fwrite( &objects.numobjects, 1, sizeof(int), tfile );
+
+ for(k=0;k<objects.numobjects;k++){
+ fwrite( &objects.type[k], 1, sizeof(int), tfile );
+ fwrite( &objects.rotation[k], 1, sizeof(float), tfile );
+ fwrite( &objects.rotation2[k], 1, sizeof(float), tfile );
+ fwrite( &objects.position[k].x, 1, sizeof(float), tfile );
+ fwrite( &objects.position[k].y, 1, sizeof(float), tfile );
+ fwrite( &objects.position[k].z, 1, sizeof(float), tfile );
+ fwrite( &objects.scale[k], 1, sizeof(float), tfile );
+ }
+
+ fwrite( &numplayers, 1, sizeof(int), tfile );
+ if(numplayers>1&&numplayers<maxplayers)
+ for(j=1;j<numplayers;j++){
+ fwrite( &player[j].whichskin, 1, sizeof(int), tfile );
+ fwrite( &player[j].creature, 1, sizeof(int), tfile );
+ fwrite( &player[j].coords.x, 1, sizeof(float), tfile );
+ fwrite( &player[j].coords.y, 1, sizeof(float), tfile );
+ fwrite( &player[j].coords.z, 1, sizeof(float), tfile );
+ fwrite( &player[j].num_weapons, 1, sizeof(int), tfile );
+ if(player[j].num_weapons>0&&player[j].num_weapons<5)
+ for(k=0;k<player[j].num_weapons;k++){
+ fwrite( &weapons.type[player[j].weaponids[k]], 1, sizeof(int), tfile );
+ }
+ if(player[j].numwaypoints<30){
+ fwrite( &player[j].numwaypoints, 1, sizeof(int), tfile );
+ for(k=0;k<player[j].numwaypoints;k++){
+ fwrite( &player[j].waypoints[k].x, 1, sizeof(float), tfile );
+ fwrite( &player[j].waypoints[k].y, 1, sizeof(float), tfile );
+ fwrite( &player[j].waypoints[k].z, 1, sizeof(float), tfile );
+ }
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ //fwrite( &player[j].jumppath, 1, sizeof(bool), tfile );
+ }
+ else{
+ player[j].numwaypoints=0;
+ player[j].waypoint=0;
+ fwrite( &player[j].numwaypoints, 1, sizeof(int), tfile );
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ }
+ fwrite( &player[j].armorhead, 1, sizeof(int), tfile );
+ fwrite( &player[j].armorhigh, 1, sizeof(int), tfile );
+ fwrite( &player[j].armorlow, 1, sizeof(int), tfile );
+ fwrite( &player[j].protectionhead, 1, sizeof(int), tfile );
+ fwrite( &player[j].protectionhigh, 1, sizeof(int), tfile );
+ fwrite( &player[j].protectionlow, 1, sizeof(int), tfile );
+ fwrite( &player[j].metalhead, 1, sizeof(int), tfile );
+ fwrite( &player[j].metalhigh, 1, sizeof(int), tfile );
+ fwrite( &player[j].metallow, 1, sizeof(int), tfile );
+ fwrite( &player[j].power, 1, sizeof(int), tfile );
+ fwrite( &player[j].speedmult, 1, sizeof(int), tfile );
+
+ fwrite( &player[j].numclothes, 1, sizeof(int), tfile );
+ if(player[j].numclothes)
+ for(k=0;k<player[j].numclothes;k++){
+ int templength;
+ templength=strlen(player[j].clothes[k]);
+ fwrite( &templength,1,sizeof(int),tfile);
+ for(l=0;l<templength;l++)
+ fwrite( &player[j].clothes[k][l],1,sizeof(char),tfile);
+ fwrite( &player[j].clothestintr[k],1,sizeof(float),tfile);
+ fwrite( &player[j].clothestintg[k],1,sizeof(float),tfile);
+ fwrite( &player[j].clothestintb[k],1,sizeof(float),tfile);
+ }
+ }
+ fwrite( &numpathpoints, 1, sizeof(int), tfile );
+ if(numpathpoints)
+ for(j=0;j<numpathpoints;j++){
+ fwrite( &pathpoint[j].x, 1, sizeof(float), tfile );
+ fwrite( &pathpoint[j].y, 1, sizeof(float), tfile );
+ fwrite( &pathpoint[j].z, 1, sizeof(float), tfile );
+ fwrite( &numpathpointconnect[j], 1, sizeof(int), tfile );
+ for(k=0;k<numpathpointconnect[j];k++){
+ fwrite( &pathpointconnect[j][k], 1, sizeof(int), tfile );
+ }
+ }
+
+ fwrite( &mapcenter.x, 1, sizeof(float), tfile );
+ fwrite( &mapcenter.y, 1, sizeof(float), tfile );
+ fwrite( &mapcenter.z, 1, sizeof(float), tfile );
+
+ fwrite( &mapradius, 1, sizeof(float), tfile );
+
+ fclose(tfile);
+ donesomething=1;*/
+ }
+ /*
+ if(Compare(consoletext[0],"save ",0,4)){
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+ for(j=5;j<consolechars[0];j++){
+ mapname[j-5+11]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-5+11]='\0';
+
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+
+ FILE *tfile;
+ tfile=fopen( mapname, "wb" );
+ fwrite( &player[0].coords, 1, sizeof(XYZ), tfile );
+ fwrite( &player[0].rotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].targetrotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].num_weapons, 1, sizeof(int), tfile );
+ if(player[0].num_weapons>0&&player[0].num_weapons<5)
+ for(j=0;j<player[0].num_weapons;j++){
+ fwrite( &weapons.type[player[0].weaponids[j]], 1, sizeof(int), tfile );
+ }
+ fwrite( &environment, 1, sizeof(int), tfile );
+
+ fwrite( &objects.numobjects, 1, sizeof(int), tfile );
+ fwrite( &objects.type, 1, sizeof(int)*objects.numobjects, tfile );
+ fwrite( &objects.rotation, 1, sizeof(float)*objects.numobjects, tfile );
+ fwrite( &objects.position, 1, sizeof(XYZ)*objects.numobjects, tfile );
+ fwrite( &objects.scale, 1, sizeof(float)*objects.numobjects, tfile );
+
+ fwrite( &numplayers, 1, sizeof(int), tfile );
+ if(numplayers>1&&numplayers<maxplayers)
+ for(j=1;j<numplayers;j++){
+ fwrite( &player[j].coords, 1, sizeof(XYZ), tfile );
+ fwrite( &player[j].num_weapons, 1, sizeof(int), tfile );
+ if(player[j].num_weapons>0&&player[j].num_weapons<5)
+ for(k=0;k<player[j].num_weapons;k++){
+ fwrite( &weapons.type[player[j].weaponids[k]], 1, sizeof(int), tfile );
+ }
+ if(player[j].numwaypoints<30){
+ fwrite( &player[j].numwaypoints, 1, sizeof(int), tfile );
+ fwrite( &player[j].waypoints, 1, sizeof(XYZ)*player[j].numwaypoints, tfile );
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ //fwrite( &player[j].jumppath, 1, sizeof(bool), tfile );
+ }
+ else{
+ player[j].numwaypoints=0;
+ player[j].waypoint=0;
+ fwrite( &player[j].numwaypoints, 1, sizeof(int), tfile );
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ fwrite( &player[j].waypoint, 1, sizeof(int), tfile );
+ }
+ }
+ fwrite( &numpathpoints, 1, sizeof(int), tfile );
+ if(numpathpoints)
+ for(j=0;j<numpathpoints;j++){
+ fwrite( &pathpoint[j], 1, sizeof(XYZ), tfile );
+ fwrite( &numpathpointconnect[j], 1, sizeof(int), tfile );
+ for(k=0;k<numpathpointconnect[j];k++){
+ fwrite( &pathpointconnect[j][k], 1, sizeof(int), tfile );
+ }
+ }
+ fclose(tfile);
+ donesomething=1;
+ }*/
+ if(Compare(consoletext[0],"cellar door ",0,11)||Compare(consoletext[0],"cellardoor ",0,10)){
+ LoadTextureSave(":Data:Textures:Furdarko.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ /*if(Compare(consoletext[0],"Pants ",0,5)){
+ AddClothes(":Data:Textures:Pants.png",0,1,&player[i].skeleton.skinText[0],&player[i].skeleton.skinsize);
+ player[i].DoMipmaps(5,0,0,player[i].skeleton.skinsize,player[i].skeleton.skinsize);
+ donesomething=1;
+ }*/
+
+ if(Compare(consoletext[0],"tintr ",0,5)||Compare(consoletext[0],"Tintr ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ tintr=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"speed ",0,5)||Compare(consoletext[0],"Speed ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ player[0].speedmult=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"strength ",0,8)||Compare(consoletext[0],"Strength ",0,8)){
+ for(j=9;j<consolechars[0];j++){
+ mapname[j-9]=consoletext[0][j];
+ }
+
+ player[0].power=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"viewdistance ",0,12)||Compare(consoletext[0],"Viewdistance ",0,12)){
+ for(j=13;j<consolechars[0];j++){
+ mapname[j-13]=consoletext[0][j];
+ }
+
+ viewdistance=atof(mapname)*100;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"fadestart ",0,9)||Compare(consoletext[0],"Fadestart ",0,9)){
+ for(j=10;j<consolechars[0];j++){
+ mapname[j-10]=consoletext[0][j];
+ }
+
+ fadestart=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"power ",0,5)||Compare(consoletext[0],"Power ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ player[0].power=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"slomo ",0,5)||Compare(consoletext[0],"Slomo ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ slomospeed=atof(mapname);
+ slomo=1-slomo;
+ slomodelay=1000;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"slofreq ",0,7)||Compare(consoletext[0],"Slofreq ",0,7)){
+ for(j=8;j<consolechars[0];j++){
+ mapname[j-8]=consoletext[0][j];
+ }
+
+ slomofreq=atoi(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"size ",0,4)||Compare(consoletext[0],"Size ",0,4)){
+ for(j=5;j<consolechars[0];j++){
+ mapname[j-5]=consoletext[0][j];
+ }
+
+ player[0].scale=atof(mapname)*.2;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"sizenear ",0,8)||Compare(consoletext[0],"Sizenear ",0,8)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+
+ for(j=9;j<consolechars[0];j++){
+ mapname[j-9]=consoletext[0][j];
+ }
+
+ player[closest].scale=atof(mapname)*.2;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"proportionnear ",0,14)||Compare(consoletext[0],"Proportionnear ",0,14)){
+ int startpoint;
+ int alldone;
+
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+
+ alldone=0;
+ startpoint=15;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ headprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ bodyprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ armprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ legprop=atof(mapname);
+
+ if(player[closest].creature==wolftype){
+ player[closest].proportionhead=1.1*headprop;
+ player[closest].proportionbody=1.1*bodyprop;
+ player[closest].proportionarms=1.1*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ }
+
+ if(player[closest].creature==rabbittype){
+ player[closest].proportionhead=1.2*headprop;
+ player[closest].proportionbody=1.05*bodyprop;
+ player[closest].proportionarms=1.00*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ player[closest].proportionlegs.y=1.05*legprop;
+ }
+
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"sizemin ",0,7)||Compare(consoletext[0],"Sizemin ",0,7)){
+ for(i=1;i<numplayers;i++){
+ if(player[i].scale<0.8*0.2)player[i].scale=0.8*0.2;
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"tutorial ",0,8)||Compare(consoletext[0],"Tutorial ",0,8)){
+ for(j=9;j<consolechars[0];j++){
+ mapname[j-9]=consoletext[0][j];
+ }
+
+ tutoriallevel=atoi(mapname);
+
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"tintg ",0,5)||Compare(consoletext[0],"Tintg ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ tintg=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"tintb ",0,5)||Compare(consoletext[0],"Tintb ",0,5)){
+ for(j=6;j<consolechars[0];j++){
+ mapname[j-6]=consoletext[0][j];
+ }
+
+ tintb=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"hostile ",0,7)){
+ for(j=8;j<consolechars[0];j++){
+ mapname[j-8]=consoletext[0][j];
+ }
+
+ hostile=atoi(mapname);
+
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"type active ",0,11)){
+ editoractive=typeactive;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"indemo ",0,6)){
+ indemo=1;
+ hotspot[numhotspots]=player[0].coords;
+ hotspotsize[numhotspots]=0;
+ hotspottype[numhotspots]=-111;
+ mapname[0]='\0';
+ strcpy(hotspottext[numhotspots],"mapname");
+ numhotspots++;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"notindemo ",0,9)){
+ indemo=0;
+ numhotspots--;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"type sitting ",0,12)){
+ editoractive=typesitting;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"type sitting wall ",0,17)){
+ editoractive=typesittingwall;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"type sleeping ",0,13)){
+ editoractive=typesleeping;
+
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"type dead1 ",0,10)){
+ editoractive=typedead1;
+
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"type dead2 ",0,10)){
+ editoractive=typedead2;
+
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"type dead3 ",0,10)){
+ editoractive=typedead3;
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"type dead4 ",0,10)){
+ editoractive=typedead4;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"path keepwalking ",0,16)){
+ editorpathtype=wpkeepwalking;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"path pause ",0,10)){
+ editorpathtype=wppause;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"mapkilleveryone ",0,15)){
+ maptype=mapkilleveryone;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"mapgosomewhere ",0,14)){
+ maptype=mapgosomewhere;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"mapkillsomeone ",0,14)){
+ maptype=mapkillsomeone;
+
+ donesomething=1;
+
+ }
+
+ if(Compare(consoletext[0],"mapkillmost ",0,11)){
+ maptype=mapkillmost;
+
+ donesomething=1;
+
+ }
+
+ if(Compare(consoletext[0],"hs ",0,2)){
+ int startpoint;
+ int alldone;
+
+ hotspot[numhotspots]=player[0].coords;
+
+ alldone=0;
+ startpoint=3;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ hotspotsize[numhotspots]=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ hotspottype[numhotspots]=atoi(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\n';
+ mapname[j-startpoint+1]='\0';
+
+ strcpy(hotspottext[numhotspots],mapname);
+
+ numhotspots++;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"dialogue ",0,8)){
+ int startpoint;
+ int alldone;
+
+ alldone=0;
+ startpoint=9;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+ startpoint=j+1;
+
+ dialoguetype[numdialogues]=atoi(mapname);
+
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='D';
+ mapname[7]='i';
+ mapname[8]='a';
+ mapname[9]='l';
+ mapname[10]='o';
+ mapname[11]='g';
+ mapname[12]='u';
+ mapname[13]='e';
+ mapname[14]='s';
+ mapname[15]=':';
+ for(j=startpoint;j<consolechars[0];j++){
+ mapname[j-startpoint+16]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-startpoint+16]='.';
+ mapname[consolechars[0]-startpoint+17]='t';
+ mapname[consolechars[0]-startpoint+18]='x';
+ mapname[consolechars[0]-startpoint+19]='t';
+ mapname[consolechars[0]-startpoint+20]='\0';
+
+ for(j=0;j<max_dialoguelength;j++){
+ for(k=0;k<128;k++){
+ dialoguetext[numdialogues][j][k]='\0';
+ }
+ for(k=0;k<64;k++){
+ dialoguename[numdialogues][j][k]='\0';
+ }
+ }
+
+ ifstream ipstream(mapname);
+ ipstream.ignore(256,':');
+ ipstream >> numdialogueboxes[numdialogues];
+ for(i=0;i<numdialogueboxes[numdialogues];i++){
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream >> dialogueboxlocation[numdialogues][i];
+ ipstream.ignore(256,':');
+ ipstream >> dialogueboxcolor[numdialogues][i][0];
+ ipstream >> dialogueboxcolor[numdialogues][i][1];
+ ipstream >> dialogueboxcolor[numdialogues][i][2];
+ ipstream.ignore(256,':');
+ ipstream.getline(dialoguename[numdialogues][i],64);
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream.getline(dialoguetext[numdialogues][i],128);
+ for(j=0;j<128;j++){
+ if(dialoguetext[numdialogues][i][j]=='\\')dialoguetext[numdialogues][i][j]='\n';
+ }
+ ipstream.ignore(256,':');
+ ipstream >> dialogueboxsound[numdialogues][i];
+ }
+
+ for(i=0;i<numdialogueboxes[numdialogues];i++){
+ for(j=0;j<numplayers;j++){
+ participantfacing[numdialogues][i][j]=player[j].facing;
+ }
+ }
+ ipstream.close();
+
+ directing=1;
+ indialogue=0;
+ whichdialogue=numdialogues;
+
+
+ numdialogues++;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"fixdialogue ",0,11)){
+ int startpoint;
+ int alldone;
+ int whichdi;
+
+ alldone=0;
+ startpoint=12;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+ startpoint=j+1;
+
+ whichdi=atoi(mapname);
+
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='D';
+ mapname[7]='i';
+ mapname[8]='a';
+ mapname[9]='l';
+ mapname[10]='o';
+ mapname[11]='g';
+ mapname[12]='u';
+ mapname[13]='e';
+ mapname[14]='s';
+ mapname[15]=':';
+ for(j=startpoint;j<consolechars[0];j++){
+ mapname[j-startpoint+16]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-startpoint+16]='.';
+ mapname[consolechars[0]-startpoint+17]='t';
+ mapname[consolechars[0]-startpoint+18]='x';
+ mapname[consolechars[0]-startpoint+19]='t';
+ mapname[consolechars[0]-startpoint+20]='\0';
+
+ for(j=0;j<max_dialoguelength;j++){
+ for(k=0;k<128;k++){
+ dialoguetext[whichdi][j][k]='\0';
+ }
+ for(k=0;k<64;k++){
+ dialoguename[whichdi][j][k]='\0';
+ }
+ }
+
+ ifstream ipstream(mapname);
+ ipstream.ignore(256,':');
+ ipstream >> numdialogueboxes[whichdi];
+ for(i=0;i<numdialogueboxes[whichdi];i++){
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream >> dialogueboxlocation[whichdi][i];
+ ipstream.ignore(256,':');
+ ipstream >> dialogueboxcolor[whichdi][i][0];
+ ipstream >> dialogueboxcolor[whichdi][i][1];
+ ipstream >> dialogueboxcolor[whichdi][i][2];
+ ipstream.ignore(256,':');
+ ipstream.getline(dialoguename[whichdi][i],64);
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream.getline(dialoguetext[whichdi][i],128);
+ for(j=0;j<128;j++){
+ if(dialoguetext[whichdi][i][j]=='\\')dialoguetext[whichdi][i][j]='\n';
+ }
+ ipstream.ignore(256,':');
+ ipstream >> dialogueboxsound[whichdi][i];
+ }
+
+ ipstream.close();
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"fixtype ",0,7)){
+ int startpoint;
+ int alldone;
+ int whichdi;
+
+ alldone=0;
+ startpoint=8;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+ dialoguetype[0]=atoi(mapname);
+
+ startpoint=j+1;
+
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"fixrotation ",0,11)){
+ participantrotation[whichdialogue][participantfocus[whichdialogue][indialogue]]=player[participantfocus[whichdialogue][indialogue]].rotation;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"ddialogue ",0,9)){
+ numdialogues--;
+ if(numdialogues<0)numdialogues=0;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"immobile ",0,8)){
+ player[0].immobile=1;
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"mobile ",0,6)){
+ player[0].immobile=0;
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"play ",0,4)){
+ int startpoint;
+ int alldone;
+
+ alldone=0;
+ startpoint=5;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+ startpoint=j+1;
+
+ whichdialogue=atoi(mapname);
+
+ if(numdialogues>whichdialogue){
+ for(i=0;i<numdialogueboxes[whichdialogue];i++){
+ player[participantfocus[whichdialogue][i]].coords=participantlocation[whichdialogue][participantfocus[whichdialogue][i]];
+ player[participantfocus[whichdialogue][i]].rotation=participantrotation[whichdialogue][participantfocus[whichdialogue][i]];
+ player[participantfocus[whichdialogue][i]].targetrotation=participantrotation[whichdialogue][participantfocus[whichdialogue][i]];
+ player[participantfocus[whichdialogue][i]].velocity=0;
+ player[participantfocus[whichdialogue][i]].targetanimation=player[participantfocus[whichdialogue][i]].getIdle();
+ player[participantfocus[whichdialogue][i]].targetframe=0;
+ }
+
+ directing=0;
+ indialogue=0;
+
+ donesomething=1;
+
+ //if(dialogueboxsound[whichdialogue][indialogue]!=0){
+ float gLoc[3];
+ float vel[3];
+ XYZ temppos;
+ temppos=player[participantfocus[whichdialogue][indialogue]].coords;
+ temppos=temppos-viewer;
+ Normalise(&temppos);
+ temppos+=viewer;
+
+ gLoc[0]=temppos.x;
+ gLoc[1]=temppos.y;
+ gLoc[2]=temppos.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ int whichsoundplay;
+ whichsoundplay=rabbitchitter;
+ if(dialogueboxsound[whichdialogue][indialogue]==2)whichsoundplay=rabbitchitter2;
+ if(dialogueboxsound[whichdialogue][indialogue]==3)whichsoundplay=rabbitpainsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==4)whichsoundplay=rabbitpain1sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==5)whichsoundplay=rabbitattacksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==6)whichsoundplay=rabbitattack2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==7)whichsoundplay=rabbitattack3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==8)whichsoundplay=rabbitattack4sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==9)whichsoundplay=growlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==10)whichsoundplay=growl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==11)whichsoundplay=snarlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==12)whichsoundplay=snarl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==13)whichsoundplay=barksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==14)whichsoundplay=bark2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==15)whichsoundplay=bark3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==16)whichsoundplay=barkgrowlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-1)whichsoundplay=fireendsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-2)whichsoundplay=firestartsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-3)whichsoundplay=consolesuccesssound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-4)whichsoundplay=consolefailsound;
+ PlaySoundEx( whichsoundplay, samp[whichsoundplay], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsoundplay], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsoundplay], 256);
+ FSOUND_SetPaused(channels[whichsoundplay], FALSE);
+ //}
+ }
+ }
+
+
+
+
+ if(Compare(consoletext[0],"dhs ",0,3)){
+ numhotspots--;
+ if(numhotspots<0)numhotspots=0;
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"proportion ",0,10)||Compare(consoletext[0],"Proportion ",0,4)){
+ int startpoint;
+ int alldone;
+
+ alldone=0;
+ startpoint=11;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ headprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ bodyprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ armprop=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ legprop=atof(mapname);
+
+ if(player[0].creature==wolftype){
+ player[0].proportionhead=1.1*headprop;
+ player[0].proportionbody=1.1*bodyprop;
+ player[0].proportionarms=1.1*armprop;
+ player[0].proportionlegs=1.1*legprop;
+ }
+
+ if(player[0].creature==rabbittype){
+ player[0].proportionhead=1.2*headprop;
+ player[0].proportionbody=1.05*bodyprop;
+ player[0].proportionarms=1.00*armprop;
+ player[0].proportionlegs=1.1*legprop;
+ player[0].proportionlegs.y=1.05*legprop;
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"allimmobile ",0,11)||Compare(consoletext[0],"Allimmobile ",0,11)){
+ for(i=0;i<numplayers;i++){
+ if(i>0)player[i].immobile=1;
+ }
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"default ",0,7)||Compare(consoletext[0],"Default ",0,7)){
+ player[0].armorhead=1;
+ player[0].armorhigh=1;
+ player[0].armorlow=1;
+ player[0].protectionhead=1;
+ player[0].protectionhigh=1;
+ player[0].protectionlow=1;
+ player[0].metalhead=1;
+ player[0].metalhigh=1;
+ player[0].metallow=1;
+ player[0].power=1;
+ player[0].speedmult=1;
+ player[0].scale=1;
+
+ if(player[0].creature==wolftype){
+ player[0].proportionhead=1.1;
+ player[0].proportionbody=1.1;
+ player[0].proportionarms=1.1;
+ player[0].proportionlegs=1.1;
+ }
+
+ if(player[0].creature==rabbittype){
+ player[0].proportionhead=1.2;
+ player[0].proportionbody=1.05;
+ player[0].proportionarms=1.00;
+ player[0].proportionlegs=1.1;
+ player[0].proportionlegs.y=1.05;
+ }
+
+ player[0].numclothes=0;
+ if(player[0].whichskin==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==2){
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==3){
+ LoadTextureSave(":Data:Textures:Lynx.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==4){
+ LoadTextureSave(":Data:Textures:Otter.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==5){
+ LoadTextureSave(":Data:Textures:Opal.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==6){
+ LoadTextureSave(":Data:Textures:Sable.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==7){
+ LoadTextureSave(":Data:Textures:Chocolate.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==8){
+ LoadTextureSave(":Data:Textures:BW2.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+ else if(player[0].whichskin==9){
+ LoadTextureSave(":Data:Textures:WB2.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ }
+
+ editoractive=typeactive;
+ player[0].immobile=0;
+
+
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"tint ",0,4)||Compare(consoletext[0],"Tint ",0,4)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=5;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ tintr=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ tintg=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ tintb=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"sky tint ",0,8)||Compare(consoletext[0],"Sky Tint ",0,8)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=9;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxr=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxg=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxb=atof(mapname);
+
+ skyboxlightr=skyboxr;
+ skyboxlightg=skyboxg;
+ skyboxlightb=skyboxb;
+
+ SetUpLighting();
+
+ //if(skyboxtexture){
+ terrain.DoShadows();
+ objects.DoShadows();
+ /*}
+ else terrain.DoLighting();
+ */
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"sky light ",0,9)||Compare(consoletext[0],"Sky Light ",0,9)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=10;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxlightr=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxlightg=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ skyboxlightb=atof(mapname);
+
+ SetUpLighting();
+
+ //if(skyboxtexture){
+ terrain.DoShadows();
+ objects.DoShadows();
+ /*}
+ else terrain.DoLighting();
+ */
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"skybox ",0,6)||Compare(consoletext[0],"Skybox ",0,6)){
+ skyboxtexture=1-skyboxtexture;
+
+ SetUpLighting();
+ //if(skyboxtexture){
+ terrain.DoShadows();
+ objects.DoShadows();
+ /*}
+ else terrain.DoLighting();
+ */
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"protection ",0,10)||Compare(consoletext[0],"Protection ",0,10)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=11;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].protectionhead=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].protectionhigh=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].protectionlow=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"armor ",0,5)||Compare(consoletext[0],"Armor ",0,5)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=6;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].armorhead=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].armorhigh=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].armorlow=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"protectionreset ",0,15)||Compare(consoletext[0],"Protectionreset ",0,15)){
+ for(i=0;i<numplayers;i++){
+ player[i].protectionhead=1.0;
+ player[i].protectionhigh=1.0;
+ player[i].protectionlow=1.0;
+ player[i].armorhead=1.0;
+ player[i].armorhigh=1.0;
+ player[i].armorlow=1.0;
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"protectionnear ",0,14)||Compare(consoletext[0],"Protectionnear ",0,14)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=15;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].protectionhead=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].protectionhigh=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].protectionlow=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"armornear ",0,9)||Compare(consoletext[0],"Armornear ",0,9)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=10;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].armorhead=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].armorhigh=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[closest].armorlow=atof(mapname);
+
+ donesomething=1;
+ }
+
+
+ if(Compare(consoletext[0],"metal ",0,5)||Compare(consoletext[0],"Metal ",0,5)){
+ int startpoint;
+ int alldone;
+ alldone=0;
+ startpoint=6;
+ j=startpoint;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].metalhead=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+ mapname[j-startpoint]='\0';
+
+ player[0].metalhigh=atof(mapname);
+
+ j++;
+ startpoint=j;
+ while(consoletext[0][j]!='\0'&&consoletext[0][j]!=' '&&!alldone&&j<255){
+ mapname[j-startpoint]=consoletext[0][j];
+ j++;
+ if(consoletext[0][j]=='\0')alldone=1;
+ }
+
+ mapname[j-startpoint]='\0';
+
+ player[0].metallow=atof(mapname);
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"noclothesnear ",0,13)||Compare(consoletext[0],"Noclothesnear ",0,13)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ player[closest].numclothes=0;
+ if(player[closest].whichskin==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==2){
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==3){
+ LoadTextureSave(":Data:Textures:Lynx.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==4){
+ LoadTextureSave(":Data:Textures:Otter.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==5){
+ LoadTextureSave(":Data:Textures:Opal.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==6){
+ LoadTextureSave(":Data:Textures:Sable.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==7){
+ LoadTextureSave(":Data:Textures:Chocolate.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==8){
+ LoadTextureSave(":Data:Textures:BW2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==9){
+ LoadTextureSave(":Data:Textures:WB2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"noclothes ",0,9)||Compare(consoletext[0],"Noclothes ",0,9)){
+ int closest=0;
+
+ player[closest].numclothes=0;
+ if(player[closest].whichskin==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==2){
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==3){
+ LoadTextureSave(":Data:Textures:Lynx.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==4){
+ LoadTextureSave(":Data:Textures:Otter.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==5){
+ LoadTextureSave(":Data:Textures:Opal.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==6){
+ LoadTextureSave(":Data:Textures:Sable.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==7){
+ LoadTextureSave(":Data:Textures:Chocolate.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==8){
+ LoadTextureSave(":Data:Textures:BW2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==9){
+ LoadTextureSave(":Data:Textures:WB2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+
+ donesomething=1;
+ }
+
+ if((Compare(consoletext[0],"Clothes ",0,7)||Compare(consoletext[0],"clothes ",0,7))){
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='T';
+ mapname[7]='e';
+ mapname[8]='x';
+ mapname[9]='t';
+ mapname[10]='u';
+ mapname[11]='r';
+ mapname[12]='e';
+ mapname[13]='s';
+ mapname[14]=':';
+ for(j=8;j<consolechars[0];j++){
+ mapname[j-8+15]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-8+15]='.';
+ mapname[consolechars[0]-8+16]='p';
+ mapname[consolechars[0]-8+17]='n';
+ mapname[consolechars[0]-8+18]='g';
+ mapname[consolechars[0]-8+19]='\0';
+
+ //:Data:Textures:Pants.png
+
+ if(AddClothes((char *)mapname,0,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize)){
+ player[0].DoMipmaps(5,0,0,player[0].skeleton.skinsize,player[0].skeleton.skinsize);
+ strcpy(player[0].clothes[player[0].numclothes],mapname);
+ player[0].clothestintr[player[0].numclothes]=tintr;
+ player[0].clothestintg[player[0].numclothes]=tintg;
+ player[0].clothestintb[player[0].numclothes]=tintb;
+ player[0].numclothes++;
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"belt ",0,4)||Compare(consoletext[0],"belt ",0,4)){
+ player[0].skeleton.clothes = 1-player[0].skeleton.clothes;
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"Cellophane ",0,10)||Compare(consoletext[0],"cellophane ",0,10)){
+ cellophane=1-cellophane;
+
+ if(cellophane){
+ for(i=0;i<numplayers;i++){
+ player[i].proportionhead.z=0;
+ player[i].proportionbody.z=0;
+ player[i].proportionarms.z=0;
+ player[i].proportionlegs.z=0;
+ }
+ }
+
+ if(!cellophane){
+ for(i=0;i<numplayers;i++){
+ player[i].proportionhead.z=player[i].proportionhead.x;
+ player[i].proportionbody.z=player[i].proportionbody.x;
+ player[i].proportionarms.z=player[i].proportionarms.x;
+ player[i].proportionlegs.z=player[i].proportionlegs.x;
+ }
+ }
+
+ donesomething=1;
+ }
+
+ if((Compare(consoletext[0],"Clothesnear ",0,11)||Compare(consoletext[0],"clothesnear ",0,11))){
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='T';
+ mapname[7]='e';
+ mapname[8]='x';
+ mapname[9]='t';
+ mapname[10]='u';
+ mapname[11]='r';
+ mapname[12]='e';
+ mapname[13]='s';
+ mapname[14]=':';
+ for(j=12;j<consolechars[0];j++){
+ mapname[j-12+15]=consoletext[0][j];
+ }
+ mapname[consolechars[0]-12+15]='.';
+ mapname[consolechars[0]-12+16]='p';
+ mapname[consolechars[0]-12+17]='n';
+ mapname[consolechars[0]-12+18]='g';
+ mapname[consolechars[0]-12+19]='\0';
+
+ //:Data:Textures:Pants.png
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+
+ if(AddClothes((char *)mapname,0,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize)){
+ player[closest].DoMipmaps(5,0,0,player[closest].skeleton.skinsize,player[closest].skeleton.skinsize);
+ strcpy(player[closest].clothes[player[closest].numclothes],mapname);
+ player[closest].clothestintr[player[closest].numclothes]=tintr;
+ player[closest].clothestintg[player[closest].numclothes]=tintg;
+ player[closest].clothestintb[player[closest].numclothes]=tintb;
+ player[closest].numclothes++;
+ }
+
+ donesomething=1;
+ }
+
+ if(Compare(consoletext[0],"funnybunny ",0,10)||Compare(consoletext[0],"funny bunny ",0,11)){
+ player[0].skeleton.id=0;
+ player[0].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+ LoadTextureSave(":Data:Textures:fur3.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ player[0].creature=rabbittype;
+ player[0].scale=.2;
+
+ player[0].proportionhead=1.2;
+ player[0].proportionbody=1.05;
+ player[0].proportionarms=1.00;
+ player[0].proportionlegs=1.1;
+ player[0].proportionlegs.y=1.05;
+ player[0].headless=0;
+
+ player[0].damagetolerance=200;
+
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"wolfieisgod ",0,11)||Compare(consoletext[0],"wolfie is god ",0,12)){
+ player[0].skeleton.id=0;
+ player[0].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf",(char *)":Data:Skeleton:Basic Figure Wolf Low",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Wolf.solid",(char *)":Data:Models:Wolf2.solid",(char *)":Data:Models:Wolf3.solid",(char *)":Data:Models:Wolf4.solid",(char *)":Data:Models:Wolf5.solid",(char *)":Data:Models:Wolf6.solid",(char *)":Data:Models:Wolf7.solid",(char *)":Data:Models:Wolflow.solid",(char *)":Data:Models:Belt.solid",0);
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ player[0].creature=wolftype;
+
+ player[0].proportionhead=1.1;
+ player[0].proportionbody=1.1;
+ player[0].proportionarms=1.1;
+ player[0].proportionlegs=1.1;
+ player[0].proportionlegs.y=1.1;
+ player[0].scale=.23;
+
+ player[0].damagetolerance=300;
+
+ donesomething=1;
+ }
+ /*if(Compare(consoletext[0],"kungfu ",0,6)||Compare(consoletext[0],"kung fu ",0,7)){
+ LoadTextureSave(":Data:Textures:Kungfu.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"rambo ",0,5)){
+ LoadTextureSave(":Data:Textures:Leather.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"david ",0,5)){
+ LoadTextureSave(":Data:Textures:David.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }*/
+ if(Compare(consoletext[0],"wolf ",0,4)){
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"darkwolf ",0,8)){
+ LoadTextureSave(":Data:Textures:DarkWolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"snowwolf ",0,8)){
+ LoadTextureSave(":Data:Textures:Snowwolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }/*
+ if(Compare(consoletext[0],"lizardwolf ",0,10)){
+ LoadTextureSave(":Data:Textures:Lizardwolf.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }*/
+ if(Compare(consoletext[0],"white ",0,5)){
+ LoadTextureSave(":Data:Textures:fur.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"brown ",0,5)){
+ LoadTextureSave(":Data:Textures:fur3.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(Compare(consoletext[0],"black ",0,5)){
+ LoadTextureSave(":Data:Textures:fur2.jpg",&player[0].skeleton.drawmodel.textureptr,1,&player[0].skeleton.skinText[0],&player[0].skeleton.skinsize);
+ donesomething=1;
+ }
+ if(consolechars[0]>0){
+ for(k=14;k>=1;k--){
+ for(j=0;j<255;j++){
+ consoletext[k][j]=consoletext[k-1][j];
+ }
+ consolechars[k]=consolechars[k-1];
+ }
+ for(j=0;j<255;j++){
+ consoletext[0][j]=' ';
+ }
+ consolechars[0]=0;
+ consoleselected=0;
+
+ if(!donesomething){
+ PlaySoundEx( consolefailsound, samp[consolefailsound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolefailsound], 256);
+ FSOUND_SetPaused(channels[consolefailsound], FALSE);
+ }
+ }
+ }
+ }
+ togglekey[i]=1;
+ }
+ else {
+ togglekey[i]=0;
+ togglekeydelay[i]=0;
+ }
+ }
+
+ consoleblinkdelay-=multiplier;
+ if(consoleblinkdelay<=0){
+ consoleblinkdelay=.3;
+ consoleblink=1-consoleblink;
+ }
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_Q_KEY)&&IsKeyDown(theKeyMap, MAC_COMMAND_KEY)){
+ tryquit=1;
+ if(mainmenu==3){
+ if(newdetail>2)newdetail=detail;
+ if(newdetail<0)newdetail=detail;
+ if(newscreenwidth>3000)newscreenwidth=screenwidth;
+ if(newscreenwidth<0)newscreenwidth=screenwidth;
+ if(newscreenheight>3000)newscreenheight=screenheight;
+ if(newscreenheight<0)newscreenheight=screenheight;
+
+ //ofstream opstream(":Data:config.txt");
+ ofstream opstream("./Data/config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << newscreenwidth;
+ opstream << "\nScreenheight:\n";
+ opstream << newscreenheight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << newdetail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ if(oldgamespeed==0)oldgamespeed=1;
+ opstream << oldgamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nVolume:\n";
+ opstream << volume;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(chatkey);
+ opstream.close();
+ }
+ }
+
+ static int oldwinfreeze;
+ if(winfreeze&&!oldwinfreeze){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ }
+ if(winfreeze==0)oldwinfreeze=winfreeze;
+ else oldwinfreeze++;
+
+ if((IsKeyDown(theKeyMap, jumpkey)||IsKeyDown(theKeyMap, MAC_SPACE_KEY))&&!oldjumpkeydown&&!campaign){
+ if(winfreeze)winfreeze=0;
+ oldjumpkeydown=1;
+ }
+ if((IsKeyDown(theKeyMap, MAC_ESCAPE_KEY))&&!campaign&&gameon){
+ if(winfreeze){
+ mainmenu=9;
+ gameon=0;
+ }
+ }
+ if((IsKeyDown(theKeyMap, jumpkey)||IsKeyDown(theKeyMap, MAC_SPACE_KEY))){
+ oldjumpkeydown=1;
+ }
+ if(!IsKeyDown(theKeyMap, jumpkey)&&!IsKeyDown(theKeyMap, MAC_SPACE_KEY))oldjumpkeydown=0;
+
+ if(!freeze&&!winfreeze&&!(mainmenu&&gameon)&&(gameon||!gamestarted)){
+
+ static bool oldbuttondialogue;
+
+ if(indialogue!=-1)talkdelay=1;
+ talkdelay-=multiplier;
+
+ if(talkdelay<=0)
+ if(indialogue==-1&&(animation[player[0].targetanimation].height!=highheight)/*&&!hostile*/)
+ for(i=0;i<numdialogues;i++){
+ int realdialoguetype;
+ bool special;
+ if(dialoguetype[i]>49){
+ realdialoguetype=dialoguetype[i]-50;
+ special=1;
+ }
+ else if(dialoguetype[i]>39){
+ realdialoguetype=dialoguetype[i]-40;
+ special=1;
+ }
+ else if(dialoguetype[i]>29){
+ realdialoguetype=dialoguetype[i]-30;
+ special=1;
+ }
+ else if(dialoguetype[i]>19){
+ realdialoguetype=dialoguetype[i]-20;
+ special=1;
+ }
+ else if(dialoguetype[i]>9){
+ realdialoguetype=dialoguetype[i]-10;
+ special=1;
+ }
+ else {
+ realdialoguetype=dialoguetype[i];
+ special=0;
+ }
+ if((!hostile||(dialoguetype[i]>40&&dialoguetype[i]<50))&&realdialoguetype<numplayers&&realdialoguetype>0&&(dialoguegonethrough[i]==0||!special)&&(special||(IsKeyDown(theKeyMap, attackkey)&&!oldbuttondialogue))){
+ if(findDistancefast(&player[0].coords,&player[realdialoguetype].coords)<6||player[realdialoguetype].howactive>=typedead1||(dialoguetype[i]>40&&dialoguetype[i]<50)){
+ whichdialogue=i;
+ for(j=0;j<numdialogueboxes[whichdialogue];j++){
+ player[participantfocus[whichdialogue][j]].coords=participantlocation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].rotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].targetrotation=participantrotation[whichdialogue][participantfocus[whichdialogue][j]];
+ player[participantfocus[whichdialogue][j]].velocity=0;
+ player[participantfocus[whichdialogue][j]].targetanimation=player[participantfocus[whichdialogue][j]].getIdle();
+ player[participantfocus[whichdialogue][j]].targetframe=0;
+ }
+ directing=0;
+ indialogue=0;
+ dialoguetime=0;
+ dialoguegonethrough[i]++;
+ if(dialogueboxsound[whichdialogue][indialogue]!=0){
+ static float gLoc[3];
+ static float vel[3];
+ XYZ temppos;
+ temppos=player[participantfocus[whichdialogue][indialogue]].coords;
+ temppos=temppos-viewer;
+ Normalise(&temppos);
+ temppos+=viewer;
+
+ gLoc[0]=temppos.x;
+ gLoc[1]=temppos.y;
+ gLoc[2]=temppos.z;vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ int whichsoundplay;
+ if(dialogueboxsound[whichdialogue][indialogue]==1)whichsoundplay=rabbitchitter;
+ if(dialogueboxsound[whichdialogue][indialogue]==2)whichsoundplay=rabbitchitter2;
+ if(dialogueboxsound[whichdialogue][indialogue]==3)whichsoundplay=rabbitpainsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==4)whichsoundplay=rabbitpain1sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==5)whichsoundplay=rabbitattacksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==6)whichsoundplay=rabbitattack2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==7)whichsoundplay=rabbitattack3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==8)whichsoundplay=rabbitattack4sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==9)whichsoundplay=growlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==10)whichsoundplay=growl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==11)whichsoundplay=snarlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==12)whichsoundplay=snarl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==13)whichsoundplay=barksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==14)whichsoundplay=bark2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==15)whichsoundplay=bark3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==16)whichsoundplay=barkgrowlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-1)whichsoundplay=fireendsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-2)whichsoundplay=firestartsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-3)whichsoundplay=consolesuccesssound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-4)whichsoundplay=consolefailsound;
+ PlaySoundEx( whichsoundplay, samp[whichsoundplay], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsoundplay], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsoundplay], 256);
+ FSOUND_SetPaused(channels[whichsoundplay], FALSE);
+ }
+ if(IsKeyDown(theKeyMap, attackkey))oldbuttondialogue=1;
+ }
+ }
+ }
+
+ windvar+=multiplier;
+ smoketex+=multiplier;
+ tutorialstagetime+=multiplier;
+
+ static float hotspotvisual[40];
+ if(numhotspots){
+ XYZ hotspotsprite;
+ if(editorenabled)
+ for(i=0;i<numhotspots;i++)
+ hotspotvisual[i]-=multiplier/320;
+
+ for(i=0;i<numhotspots;i++){
+ //if(hotspottype[i]<=10)
+ while(hotspotvisual[i]<0){
+ hotspotsprite=0;
+ hotspotsprite.x=float(abs(Random()%100000))/100000*hotspotsize[i];
+ hotspotsprite=DoRotation(hotspotsprite,0,0,Random()%360);
+ hotspotsprite=DoRotation(hotspotsprite,0,Random()%360,0);
+ hotspotsprite+=hotspot[i];
+ sprites.MakeSprite(breathsprite, hotspotsprite, hotspotsprite*0, 1,0.5,0, 7, 0.4);
+ hotspotvisual[i]+=0.1/hotspotsize[i]/hotspotsize[i]/hotspotsize[i];
+ }
+ }
+
+ for(i=0;i<numhotspots;i++){
+ if(hotspottype[i]<=10&&hotspottype[i]>0){
+ hotspot[i]=player[hotspottype[i]].coords;
+ }
+ }
+ }
+
+ //Tutorial
+ if(tutoriallevel&&tutorialstagetime>tutorialmaxtime){
+ tutorialstage++;
+ tutorialsuccess=0;
+ if(tutorialstage<=1){
+ canattack=0;
+ cananger=0;
+ reversaltrain=0;
+ }
+ if(tutorialstage==1){
+ tutorialmaxtime=5;
+ }
+ if(tutorialstage==2){
+ tutorialmaxtime=2;
+ }
+ if(tutorialstage==3){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==4){
+ tutorialmaxtime=1000;
+ }
+ if(tutorialstage==5){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==6){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==7){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==8){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==9){
+ tutorialmaxtime=600;
+ }
+ if(tutorialstage==10){
+ tutorialmaxtime=2;
+ }
+ if(tutorialstage==11){
+ tutorialmaxtime=1000;
+ }
+ if(tutorialstage==12){
+ tutorialmaxtime=1000;
+ }
+ if(tutorialstage==13){
+ tutorialmaxtime=2;
+ }
+ if(tutorialstage==14){
+ tutorialmaxtime=3;
+
+ XYZ temp,temp2;
+
+ temp.x=1011;
+ temp.y=84;
+ temp.z=491;
+ temp2.x=1025;
+ temp2.y=75;
+ temp2.z=447;
+
+ player[1].coords=(temp+temp2)/2;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[1].coords.x;
+ gLoc[1]=player[1].coords.y;
+ gLoc[2]=player[1].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+
+ for(i=0;i<player[1].skeleton.num_joints;i++){
+ if(Random()%2==0){
+ if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
+ if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
+ if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
+ if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
+ sprites.MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
+ }
+ }
+
+ }
+ if(tutorialstage==15){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==16){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==17){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==18){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==19){
+ tutorialstage=20;
+ //tutorialmaxtime=500;
+ }
+ if(tutorialstage==20){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==21){
+ tutorialmaxtime=500;
+ if(bonus==cannon){
+ bonus=Slicebonus;
+ againbonus=1;
+ }
+ else againbonus=0;
+ }
+ if(tutorialstage==22){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==23){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==24){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==25){
+ tutorialmaxtime=500;
+ }
+ if(tutorialstage==26){
+ tutorialmaxtime=2;
+ }
+ if(tutorialstage==27){
+ tutorialmaxtime=4;
+ reversaltrain=1;
+ cananger=1;
+ player[1].aitype=attacktypecutoff;
+ }
+ if(tutorialstage==28){
+ tutorialmaxtime=400;
+ }
+ if(tutorialstage==29){
+ tutorialmaxtime=400;
+ player[0].escapednum=0;
+ }
+ if(tutorialstage==30){
+ tutorialmaxtime=4;
+ reversaltrain=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+ }
+ if(tutorialstage==31){
+ tutorialmaxtime=13;
+ }
+ if(tutorialstage==32){
+ tutorialmaxtime=8;
+ }
+ if(tutorialstage==33){
+ tutorialmaxtime=400;
+ cananger=1;
+ canattack=1;
+ player[1].aitype=attacktypecutoff;
+ }
+ if(tutorialstage==34){
+ tutorialmaxtime=400;
+ }
+ if(tutorialstage==35){
+ tutorialmaxtime=400;
+ }
+ if(tutorialstage==36){
+ tutorialmaxtime=2;
+ reversaltrain=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+ }
+ if(tutorialstage==37){
+ damagedealt=0;
+ damagetaken=0;
+ tutorialmaxtime=50;
+ cananger=1;
+ canattack=1;
+ player[1].aitype=attacktypecutoff;
+ }
+ if(tutorialstage==38){
+ tutorialmaxtime=4;
+ canattack=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+ }
+ if(tutorialstage==39){
+ XYZ temp,temp2;
+
+ temp.x=1011;
+ temp.y=84;
+ temp.z=491;
+ temp2.x=1025;
+ temp2.y=75;
+ temp2.z=447;
+
+
+ weapons.owner[weapons.numweapons]=-1;
+ weapons.type[weapons.numweapons]=knife;
+ weapons.damage[weapons.numweapons]=0;
+ weapons.mass[weapons.numweapons]=1;
+ weapons.tipmass[weapons.numweapons]=1.2;
+ weapons.length[weapons.numweapons]=.25;
+ weapons.position[weapons.numweapons]=(temp+temp2)/2;
+ weapons.tippoint[weapons.numweapons]=(temp+temp2)/2;
+
+ weapons.velocity[weapons.numweapons]=0.1;
+ weapons.tipvelocity[weapons.numweapons]=0.1;
+ weapons.missed[weapons.numweapons]=1;
+ weapons.hitsomething[weapons.numweapons]=0;
+ weapons.freetime[weapons.numweapons]=0;
+ weapons.firstfree[weapons.numweapons]=1;
+ weapons.physics[weapons.numweapons]=1;
+
+ weapons.numweapons++;
+ }
+ if(tutorialstage==40){
+ tutorialmaxtime=300;
+ }
+ if(tutorialstage==41){
+ tutorialmaxtime=300;
+ }
+ if(tutorialstage==42){
+ tutorialmaxtime=8;
+ }
+ if(tutorialstage==43){
+ tutorialmaxtime=300;
+ }
+ if(tutorialstage==44){
+ weapons.owner[0]=1;
+ player[0].weaponactive=-1;
+ player[0].num_weapons=0;
+ player[1].weaponactive=0;
+ player[1].num_weapons=1;
+ player[1].weaponids[0]=0;
+
+ cananger=1;
+ canattack=1;
+ player[1].aitype=attacktypecutoff;
+
+ tutorialmaxtime=300;
+ }
+ if(tutorialstage==45){
+ weapons.owner[0]=1;
+ player[0].weaponactive=-1;
+ player[0].num_weapons=0;
+ player[1].weaponactive=0;
+ player[1].num_weapons=1;
+ player[1].weaponids[0]=0;
+
+ tutorialmaxtime=300;
+ }
+ if(tutorialstage==46){
+ weapons.owner[0]=1;
+ player[0].weaponactive=-1;
+ player[0].num_weapons=0;
+ player[1].weaponactive=0;
+ player[1].num_weapons=1;
+ player[1].weaponids[0]=0;
+
+ weapons.type[0]=sword;
+
+ tutorialmaxtime=300;
+ }
+
+ if(tutorialstage==47){
+ tutorialmaxtime=10;
+
+ XYZ temp,temp2;
+
+ temp.x=1011;
+ temp.y=84;
+ temp.z=491;
+ temp2.x=1025;
+ temp2.y=75;
+ temp2.z=447;
+
+ weapons.owner[weapons.numweapons]=-1;
+ weapons.type[weapons.numweapons]=sword;
+ weapons.damage[weapons.numweapons]=0;
+ weapons.mass[weapons.numweapons]=1;
+ weapons.tipmass[weapons.numweapons]=1.2;
+ weapons.length[weapons.numweapons]=.25;
+ weapons.position[weapons.numweapons]=(temp+temp2)/2;
+ weapons.tippoint[weapons.numweapons]=(temp+temp2)/2;
+
+ weapons.velocity[weapons.numweapons]=0.1;
+ weapons.tipvelocity[weapons.numweapons]=0.1;
+ weapons.missed[weapons.numweapons]=1;
+ weapons.hitsomething[weapons.numweapons]=0;
+ weapons.freetime[weapons.numweapons]=0;
+ weapons.firstfree[weapons.numweapons]=1;
+ weapons.physics[weapons.numweapons]=1;
+
+ weapons.owner[0]=1;
+ weapons.owner[1]=0;
+ player[0].weaponactive=0;
+ player[0].num_weapons=1;
+ player[0].weaponids[0]=1;
+ player[1].weaponactive=0;
+ player[1].num_weapons=1;
+ player[1].weaponids[0]=0;
+
+ weapons.numweapons++;
+ }
+ if(tutorialstage==48){
+ canattack=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+
+ tutorialmaxtime=15;
+
+ weapons.owner[0]=1;
+ weapons.owner[1]=0;
+ player[0].weaponactive=0;
+ player[0].num_weapons=1;
+ player[0].weaponids[0]=1;
+ player[1].weaponactive=0;
+ player[1].num_weapons=1;
+ player[1].weaponids[0]=0;
+
+ if(player[0].weaponactive!=-1)weapons.type[player[0].weaponids[player[0].weaponactive]]=staff;
+ else weapons.type[0]=staff;
+
+ weapons.numweapons++;
+ }
+ if(tutorialstage==49){
+ canattack=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+
+ tutorialmaxtime=200;
+
+ weapons.position[1]=1000;
+ weapons.tippoint[1]=1000;
+
+ weapons.numweapons=1;
+ weapons.owner[0]=0;
+ player[1].weaponactive=-1;
+ player[1].num_weapons=0;
+ player[0].weaponactive=0;
+ player[0].num_weapons=1;
+ player[0].weaponids[0]=0;
+
+ weapons.type[0]=knife;
+
+ weapons.numweapons++;
+ }
+ if(tutorialstage==50){
+ tutorialmaxtime=8;
+
+ XYZ temp,temp2;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[1].coords.x;
+ gLoc[1]=player[1].coords.y;
+ gLoc[2]=player[1].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+
+ for(i=0;i<player[1].skeleton.num_joints;i++){
+ if(Random()%2==0){
+ if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
+ if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
+ if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
+ if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
+ sprites.MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
+ }
+ }
+
+ player[1].num_weapons=0;
+ player[1].weaponstuck=-1;
+ player[1].weaponactive=-1;
+
+ weapons.numweapons=0;
+
+ weapons.owner[0]=-1;
+ weapons.velocity[0]=0.1;
+ weapons.tipvelocity[0]=-0.1;
+ weapons.missed[0]=1;
+ weapons.hitsomething[0]=0;
+ weapons.freetime[0]=0;
+ weapons.firstfree[0]=1;
+ weapons.physics[0]=1;
+ }
+ if(tutorialstage==51){
+ tutorialmaxtime=80000;
+ }
+ if(tutorialstage<=51)tutorialstagetime=0;
+ }
+
+ //Tutorial success
+ if(tutoriallevel&&tutorialstagetime<tutorialmaxtime-3){
+ if(tutorialstage==3){
+ if(deltah||deltav)tutorialsuccess+=multiplier;
+ }
+ if(tutorialstage==4){
+ if(player[0].forwardkeydown||player[0].backkeydown||player[0].leftkeydown||player[0].rightkeydown)tutorialsuccess+=multiplier;
+ }
+ if(tutorialstage==5){
+ if(player[0].jumpkeydown)tutorialsuccess=1;
+ }
+ if(tutorialstage==6){
+ if(player[0].isCrouch())tutorialsuccess=1;
+ }
+ if(tutorialstage==7){
+ if(player[0].targetanimation==rollanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==8){
+ if(player[0].targetanimation==sneakanim)tutorialsuccess+=multiplier;
+ }
+ if(tutorialstage==9){
+ if(player[0].targetanimation==rabbitrunninganim||player[0].targetanimation==wolfrunninganim)tutorialsuccess+=multiplier;
+ }
+ if(tutorialstage==11){
+ if(player[0].isWallJump())tutorialsuccess=1;
+ }
+ if(tutorialstage==12){
+ if(player[0].targetanimation==flipanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==15){
+ if(player[0].targetanimation==upunchanim||player[0].targetanimation==winduppunchanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==16){
+ if(player[0].targetanimation==winduppunchanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==17){
+ if(player[0].targetanimation==spinkickanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==18){
+ if(player[0].targetanimation==sweepanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==19){
+ if(player[0].targetanimation==dropkickanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==20){
+ if(player[0].targetanimation==rabbitkickanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==21){
+ if(bonus==cannon)tutorialsuccess=1;
+ }
+ if(tutorialstage==22){
+ if(bonus==spinecrusher)tutorialsuccess=1;
+ }
+ if(tutorialstage==23){
+ if(player[0].targetanimation==walljumprightkickanim||player[0].targetanimation==walljumpleftkickanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==24){
+ if(player[0].targetanimation==rabbittacklinganim)tutorialsuccess=1;
+ }
+ if(tutorialstage==25){
+ if(player[0].targetanimation==backhandspringanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==28){
+ if(animation[player[0].targetanimation].attack==reversed&&player[0].feint)tutorialsuccess=1;
+ }
+ if(tutorialstage==29){
+ if(player[0].escapednum==2){
+ tutorialsuccess=1;
+ reversaltrain=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+ }
+ }
+ if(tutorialstage==33){
+ if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
+ }
+ if(tutorialstage==34){
+ if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
+ }
+ if(tutorialstage==35){
+ if(animation[player[0].targetanimation].attack==reversal){
+ tutorialsuccess=1;
+ reversaltrain=0;
+ cananger=0;
+ player[1].aitype=passivetype;
+ }
+ }
+ if(tutorialstage==40){
+ if(player[0].num_weapons>0)tutorialsuccess=1;
+ }
+ if(tutorialstage==41){
+ if(player[0].weaponactive==-1&&player[0].num_weapons>0)tutorialsuccess=1;
+ }
+ if(tutorialstage==43){
+ if(player[0].targetanimation==knifeslashstartanim)tutorialsuccess=1;
+ }
+ if(tutorialstage==44){
+ if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
+ }
+ if(tutorialstage==45){
+ if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
+ }
+ if(tutorialstage==46){
+ if(animation[player[0].targetanimation].attack==reversal)tutorialsuccess=1;
+ }
+ if(tutorialstage==49){
+ if(player[1].weaponstuck!=-1)tutorialsuccess=1;
+ }
+ if(tutorialsuccess>=1)tutorialstagetime=tutorialmaxtime-3;
+
+
+ if(tutorialstagetime==tutorialmaxtime-3){
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ }
+
+ if(tutorialsuccess>=1){
+ if(tutorialstage==34||tutorialstage==35)
+ tutorialstagetime=tutorialmaxtime-1;
+ }
+ }
+
+ if(tutoriallevel){
+ if(tutorialstage<14||tutorialstage>=50){
+ player[1].coords.y=300;
+ player[1].velocity=0;
+ }
+ }
+
+ if(tutoriallevel!=1){
+ if(bonustime==0&&bonus!=solidhit&&bonus!=spinecrusher&&bonus!=tracheotomy&&bonus!=backstab&&bonusvalue>10){
+ PlaySoundEx( consolesuccesssound, samp[consolesuccesssound], NULL, TRUE);
+ FSOUND_SetVolume(channels[consolesuccesssound], 256);
+ FSOUND_SetPaused(channels[consolesuccesssound], FALSE);
+ }
+ }
+ else
+ if(bonustime==0){
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ }
+ if(bonustime==0){
+ if(bonus!=solidhit&&bonus!=twoxcombo&&bonus!=threexcombo&&bonus!=fourxcombo&&bonus!=megacombo)bonusnum[bonus]++;
+ else bonusnum[bonus]+=0.15;
+ if(tutoriallevel)bonusvalue=0;
+ bonusvalue/=bonusnum[bonus];
+ bonustotal+=bonusvalue;
+ }
+ bonustime+=multiplier;
+
+ if(environment==snowyenvironment){
+ precipdelay-=multiplier;
+ while(precipdelay<0){
+ precipdelay+=.04;
+ if(!detail)precipdelay+=.04;
+ XYZ footvel,footpoint;
+
+ footvel=0;
+ footpoint=viewer+viewerfacing*6;
+ footpoint.y+=((float)abs(Random()%1200))/100-6;
+ footpoint.x+=((float)abs(Random()%1200))/100-6;
+ footpoint.z+=((float)abs(Random()%1200))/100-6;
+ sprites.MakeSprite(snowsprite, footpoint,footvel, 1,1,1, .1, 1);
+ }
+ }
+ for(k=0;k<numplayers;k++){
+ if(player[k].aitype==playercontrolled)player[k].turnspeed=500;
+ if(player[k].aitype!=playercontrolled)player[k].turnspeed=500;
+
+ if((player[k].isRun()&&((player[k].targetrotation!=rabbitrunninganim&&player[k].targetrotation!=wolfrunninganim)||player[k].targetframe==4))||player[k].targetanimation==removeknifeanim||player[k].targetanimation==crouchremoveknifeanim||player[k].targetanimation==flipanim||player[k].targetanimation==fightsidestep||player[k].targetanimation==walkanim){
+ if(abs(player[k].rotation-player[k].targetrotation)<multiplier*player[k].turnspeed)player[k].rotation=player[k].targetrotation;
+ else if(player[k].rotation>player[k].targetrotation){
+ player[k].rotation-=multiplier*player[k].turnspeed;
+ }
+ else if(player[k].rotation<player[k].targetrotation){
+ player[k].rotation+=multiplier*player[k].turnspeed;
+ }
+ }
+
+
+ if(player[k].isStop()||player[k].isLanding()||player[k].targetanimation==staggerbackhighanim||(player[k].targetanimation==sneakanim&&player[k].currentanimation==sneakanim)||player[k].targetanimation==staggerbackhardanim||player[k].targetanimation==backhandspringanim||player[k].targetanimation==dodgebackanim||player[k].targetanimation==rollanim||(animation[player[k].targetanimation].attack&&player[k].targetanimation!=rabbitkickanim&&(player[k].targetanimation!=crouchstabanim||player[k].hasvictim)&&(player[k].targetanimation!=swordgroundstabanim||player[k].hasvictim))){
+ player[k].turnspeed*=2;
+ if(abs(player[k].rotation-player[k].targetrotation)<multiplier*player[k].turnspeed)player[k].rotation=player[k].targetrotation;
+ else if(player[k].rotation>player[k].targetrotation){
+ player[k].rotation-=multiplier*player[k].turnspeed;
+ }
+ else if(player[k].rotation<player[k].targetrotation){
+ player[k].rotation+=multiplier*player[k].turnspeed;
+ }
+ player[k].turnspeed/=2;
+ }
+
+ if(player[k].targetanimation==sneakanim&&player[k].currentanimation!=sneakanim){
+ player[k].turnspeed*=4;
+ if(abs(player[k].rotation-player[k].targetrotation)<multiplier*player[k].turnspeed)player[k].rotation=player[k].targetrotation;
+ else if(player[k].rotation>player[k].targetrotation){
+ player[k].rotation-=multiplier*player[k].turnspeed;
+ }
+ else if(player[k].rotation<player[k].targetrotation){
+ player[k].rotation+=multiplier*player[k].turnspeed;
+ }
+ player[k].turnspeed/=4;
+ }
+
+ /*if(player[k].aitype!=passivetype||(findDistancefast(&player[k].coords,&viewer)<viewdistance*viewdistance))*/ player[k].DoStuff();
+ if(player[k].immobile&&k!=0)player[k].coords=player[k].realoldcoords;
+
+ if(findDistancefast(&player[k].coords,&player[k].realoldcoords)>0){
+ if(!player[k].skeleton.free&&player[k].targetanimation!=climbanim&&player[k].targetanimation!=hanganim){
+ bool tempcollide=0;
+
+ if(player[k].collide<-.3)player[k].collide=-.3;
+ if(player[k].collide>1)player[k].collide=1;
+ player[k].collide-=multiplier*30;
+
+ if(player[k].coords.y<terrain.getHeight(player[k].coords.x,player[k].coords.z)){
+ player[k].coords.y=terrain.getHeight(player[k].coords.x,player[k].coords.z);
+ }
+ if(terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz])
+ for(l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ if(objects.type[i]!=rocktype||(((objects.scale[i]>.5&&player[k].aitype==playercontrolled)||objects.position[i].y>player[k].coords.y))){
+ lowpoint=player[k].coords;
+ if(player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim&&!player[k].isFlip())lowpoint.y+=1.25;
+ else lowpoint.y+=1.3;
+ if(player[k].coords.y<terrain.getHeight(player[k].coords.x,player[k].coords.z)&&player[k].coords.y>terrain.getHeight(player[k].coords.x,player[k].coords.z)-.1){
+ player[k].coords.y=terrain.getHeight(player[k].coords.x,player[k].coords.z);
+ }
+ /*while(player[k].coords.y<terrain.getHeight(player[k].coords.x,player[k].coords.z))
+ player[k].coords+=terrain.getNormal(player[k].coords.x,player[k].coords.z)/50;
+ */
+ if(player[k].SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.rotation[i], &objects.model[i])!=-1){
+ flatfacing=lowpoint-player[k].coords;
+ player[k].coords=lowpoint;
+ player[k].coords.y-=1.3;
+ player[k].collide=1;
+ tempcollide=1;
+ if(player[k].aitype==playercontrolled&&(player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim||player[k].isFlip())&&!player[k].jumptogglekeydown&&player[k].jumpkeydown){
+ lowpointtarget=lowpoint+DoRotation(player[k].facing,0,-90,0)*1.5;
+ tempcoords1=lowpoint;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&abs(objects.model[i].facenormals[whichhit].y)<.3){
+ player[k].target=0;
+ player[k].targetanimation=walljumpleftanim;
+ player[k].targetframe=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 256);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+ if(k==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x);
+ player[k].rotation*=360/6.28;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint+DoRotation(player[k].facing,0,90,0)*1.5;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&abs(objects.model[i].facenormals[whichhit].y)<.3){
+ player[k].target=0;
+ player[k].targetanimation=walljumprightanim;
+ player[k].targetframe=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 256);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+ if(k==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x);
+ player[k].rotation*=360/6.28;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint+player[k].facing*2;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&abs(objects.model[i].facenormals[whichhit].y)<.3){
+ player[k].target=0;
+ player[k].targetanimation=walljumpbackanim;
+ player[k].targetframe=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 256);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+ if(k==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x);
+ player[k].rotation*=360/6.28;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint-player[k].facing*2;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&abs(objects.model[i].facenormals[whichhit].y)<.3){
+ player[k].target=0;
+ player[k].targetanimation=walljumpfrontanim;
+ player[k].targetframe=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 256);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+ if(k==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x);
+ player[k].rotation*=360/6.28;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].rotation+=180;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if(objects.type[i]==rocktype){
+ lowpoint2=player[k].coords;
+ lowpoint=player[k].coords;
+ lowpoint.y+=2;
+ if(objects.model[i].LineCheck(&lowpoint,&lowpoint2,&colpoint,&objects.position[i],&objects.rotation[i])!=-1){
+ player[k].coords=colpoint;
+ player[k].collide=1;
+ tempcollide=1;
+
+ if((player[k].targetanimation==jumpdownanim||player[k].isFlip())){
+ if(player[k].isFlip()&&animation[player[k].targetanimation].label[player[k].targetframe]==7)player[k].RagDoll(0);
+
+ if(player[k].targetanimation==jumpupanim){player[k].jumppower=-4;player[k].targetanimation=player[k].getIdle();}
+ player[k].target=0;
+ player[k].targetframe=0;
+ player[k].onterrain=1;
+
+ if(player[k].id==0){
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ FSOUND_SetVolume(channels[whooshsound], 0);
+ }
+
+ if((player[k].targetanimation==jumpdownanim||player[k].isFlip())&&!player[k].wasLanding()){
+ if(player[k].isFlip())player[k].jumppower=-4;
+ player[k].targetanimation=player[k].getLanding();
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=player[k].velocity.x;
+ vel[1]=player[k].velocity.y;
+ vel[2]=player[k].velocity.z;
+ PlaySoundEx( landsound, samp[landsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound], 128);
+ FSOUND_SetPaused(channels[landsound], FALSE);
+ if(k==0){
+ envsound[numenvsounds]=player[k].coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if(tempcollide&&terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz]&&(/*player[k].jumptogglekeydown*/1==1||player[k].aitype!=playercontrolled))
+ for(l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ lowpoint=player[k].coords;
+ lowpoint.y+=1.35;
+ if(objects.type[i]!=rocktype)
+ if(player[k].SphereCheck(&lowpoint, 1.33, &colpoint, &objects.position[i], &objects.rotation[i], &objects.model[i])!=-1){
+ if(player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim&&player[k].onterrain)player[k].avoidcollided=1;
+ player[k].coords=lowpoint;
+ player[k].coords.y-=1.35;
+ player[k].collide=1;
+
+ if((player[k].grabdelay<=0||player[k].aitype!=playercontrolled)&&((/*(player[k].isRun()||player[k].targetanimation==sneakanim||player[k].targetanimation==walkanim)&&*/player[k].currentanimation!=climbanim&&player[k].currentanimation!=hanganim&&!player[k].isWallJump())||player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim)){
+ lowpoint=player[k].coords;
+ objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.rotation[i]);
+ lowpoint=player[k].coords;
+ lowpoint.y+=.05;
+ facing=0;
+ facing.z=-1;
+ facing=DoRotation(facing,0,player[k].targetrotation+180,0);
+ lowpointtarget=lowpoint+facing*1.4;
+ whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1){
+ lowpoint=player[k].coords;
+ lowpoint.y+=.1;
+ lowpointtarget=lowpoint+facing*1.4;
+ lowpoint2=lowpoint;
+ lowpointtarget2=lowpointtarget;
+ lowpoint3=lowpoint;
+ lowpointtarget3=lowpointtarget;
+ lowpoint4=lowpoint;
+ lowpointtarget4=lowpointtarget;
+ lowpoint5=lowpoint;
+ lowpointtarget5=lowpointtarget;
+ lowpoint6=lowpoint;
+ lowpointtarget6=lowpointtarget;
+ lowpoint7=lowpoint;
+ lowpointtarget7=lowpoint;
+ lowpoint2.x+=.1;
+ lowpointtarget2.x+=.1;
+ lowpoint3.z+=.1;
+ lowpointtarget3.z+=.1;
+ lowpoint4.x-=.1;
+ lowpointtarget4.x-=.1;
+ lowpoint5.z-=.1;
+ lowpointtarget5.z-=.1;
+ lowpoint6.y+=45/13;
+ lowpointtarget6.y+=45/13;
+ lowpointtarget6+=facing*.6;
+ lowpointtarget7.y+=90/13;
+ whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(objects.friction[i]>.5)
+ if(whichhit!=-1){
+ //if(k==0){
+ if(whichhit!=-1)if(player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim)player[k].collided=1;
+ if(checkcollide(lowpoint7,lowpointtarget7)==-1)
+ if(checkcollide(lowpoint6,lowpointtarget6)==-1)
+ if(objects.model[i].LineCheckPossible(&lowpoint2,&lowpointtarget2,&colpoint,&objects.position[i],&objects.rotation[i])!=-1&&objects.model[i].LineCheckPossible(&lowpoint3,&lowpointtarget3,&colpoint,&objects.position[i],&objects.rotation[i])!=-1&&objects.model[i].LineCheckPossible(&lowpoint4,&lowpointtarget4,&colpoint,&objects.position[i],&objects.rotation[i])!=-1&&objects.model[i].LineCheckPossible(&lowpoint5,&lowpointtarget5,&colpoint,&objects.position[i],&objects.rotation[i])!=-1)
+ for(j=0;j<45;j++){
+ lowpoint=player[k].coords;
+ lowpoint.y+=(float)j/13;
+ lowpointtarget=lowpoint+facing*1.4;
+ if(objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint2,&objects.position[i],&objects.rotation[i])==-1){
+ if(j<=6){
+ j=100;
+ }
+ /*if(j>=25&&(player[k].isRun()||player[k].targetanimation==sneakanim||player[k].targetanimation==walkanim)){
+ j=100;
+ }*/
+ if(j<=25&&player[k].targetanimation==jumpdownanim){
+ j=100;
+ }
+ if(j!=100&&(/*j>25||(player[k].isRun()||player[k].targetanimation==sneakanim||player[k].targetanimation==walkanim)||*/player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim)){
+ lowpoint=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0);
+ if(1==1/*dotproduct(&player[k].velocity,&lowpoint)>0||player[k].aitype!=playercontrolled||(player[k].isRun()||player[k].targetanimation==sneakanim||player[k].targetanimation==walkanim||player[k].targetanimation==jumpupanim)*/){
+ lowpoint=player[k].coords;
+ lowpoint.y+=(float)j/13;
+ lowpointtarget=lowpoint+facing*1.3;
+ flatfacing=player[k].coords;
+ player[k].coords=colpoint-DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0)*.01;
+ player[k].coords.y=lowpointtarget.y-.07;
+ player[k].currentoffset=(flatfacing-player[k].coords)/player[k].scale;
+
+ if(j>10||!player[k].isRun()){
+ if(player[k].targetanimation==jumpdownanim||player[k].targetanimation==jumpupanim){
+ if(k==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=player[k].velocity.x;
+ vel[1]=player[k].velocity.y;
+ vel[2]=player[k].velocity.z;
+ PlaySoundEx( jumpsound, samp[jumpsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[jumpsound], gLoc, vel);
+ FSOUND_SetVolume(channels[jumpsound], 128);
+ FSOUND_SetPaused(channels[jumpsound], FALSE);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x);
+ player[k].rotation*=360/6.28;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+
+ //player[k].velocity=lowpointtarget*.03;
+ player[k].velocity=0;
+
+ if(/*(player[k].isRun()||player[k].targetanimation==sneakanim||player[k].targetanimation==walkanim)||*/player[k].targetanimation==jumpupanim){
+ //player[k].currentanimation=climbanim;
+ player[k].targetanimation=climbanim;
+ player[k].jumppower=0;
+ player[k].jumpclimb=1;
+ }
+ player[k].transspeed=6;
+ player[k].target=0;
+
+ //player[k].currentframe=1;
+ player[k].targetframe=1;
+ if(j>25){
+ //player[k].currentframe=0;
+ player[k].targetframe=0;
+ //player[k].currentanimation=hanganim;
+ player[k].targetanimation=hanganim;
+ player[k].jumppower=0;
+ }
+ }
+ j=100;
+ }
+ }
+ }
+ }
+ //}
+ }
+ }
+ }
+ }
+ }
+ if(player[k].collide<=0){
+ if(!player[k].onterrain&&player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim&&player[k].targetanimation!=climbanim&&player[k].targetanimation!=hanganim&&!player[k].isWallJump()&&!player[k].isFlip()){
+ if(player[k].currentanimation!=climbanim&&player[k].currentanimation!=tempanim&&player[k].targetanimation!=backhandspringanim&&(player[k].targetanimation!=rollanim||player[k].targetframe<2||player[k].targetframe>6)){
+ if(player[k].targetanimation==staggerbackhighanim||player[k].targetanimation==staggerbackhardanim)player[k].RagDoll(0);
+ player[k].targetanimation=jumpdownanim;
+ player[k].targetframe=0;
+ player[k].target=0;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[k].coords.x;
+ gLoc[1]=player[k].coords.y;
+ gLoc[2]=player[k].coords.z;
+ vel[0]=player[k].velocity.x;
+ vel[1]=player[k].velocity.y;
+ vel[2]=player[k].velocity.z;
+ if(k==0){
+ PlaySoundEx( whooshsound, samp[whooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshsound], 128);
+ FSOUND_SetPaused(channels[whooshsound], FALSE);
+ }
+ }
+ player[k].velocity.y+=gravity;
+ }
+ }
+ }
+ }
+ player[k].realoldcoords=player[k].coords;
+ }
+
+ static XYZ oldviewer;
+
+ if(indialogue==-1){
+ player[0].forwardkeydown=IsKeyDown(theKeyMap, forwardkey);
+ player[0].leftkeydown=IsKeyDown(theKeyMap, leftkey);
+ player[0].backkeydown=IsKeyDown(theKeyMap, backkey);
+ player[0].rightkeydown=IsKeyDown(theKeyMap, rightkey);
+ player[0].jumpkeydown=IsKeyDown(theKeyMap, jumpkey);
+ player[0].crouchkeydown=IsKeyDown(theKeyMap, crouchkey);
+ player[0].drawkeydown=IsKeyDown(theKeyMap, drawkey);
+ player[0].throwkeydown=IsKeyDown(theKeyMap, throwkey);
+ }
+ else
+ {
+ player[0].forwardkeydown=0;
+ player[0].leftkeydown=0;
+ player[0].backkeydown=0;
+ player[0].rightkeydown=0;
+ player[0].jumpkeydown=0;
+ player[0].crouchkeydown=0;
+ player[0].drawkeydown=0;
+ player[0].throwkeydown=0;
+ }
+
+ if(!player[0].jumpkeydown)player[0].jumpclimb=0;
+
+
+ static bool endkeydown;
+ if(indialogue!=-1){
+ cameramode=1;
+ if(directing){
+ facing=0;
+ facing.z=-1;
+
+ facing=DoRotation(facing,-rotation2,0,0);
+ facing=DoRotation(facing,0,0-rotation,0);
+
+ flatfacing=0;
+ flatfacing.z=-1;
+
+ flatfacing=DoRotation(flatfacing,0,-rotation,0);
+
+ if(IsKeyDown(theKeyMap, forwardkey))viewer+=facing*multiplier*4;
+ if(IsKeyDown(theKeyMap, backkey))viewer-=facing*multiplier*4;
+ if(IsKeyDown(theKeyMap, leftkey))viewer+=DoRotation(flatfacing*multiplier,0,90,0)*4;
+ if(IsKeyDown(theKeyMap, rightkey))viewer+=DoRotation(flatfacing*multiplier,0,-90,0)*4;
+ if(IsKeyDown(theKeyMap, jumpkey))viewer.y+=multiplier*4;
+ if(IsKeyDown(theKeyMap, crouchkey))viewer.y-=multiplier*4;
+ if(!endkeydown&&(IsKeyDown(theKeyMap, MAC_1_KEY)||IsKeyDown(theKeyMap, MAC_2_KEY)||IsKeyDown(theKeyMap, MAC_3_KEY)||IsKeyDown(theKeyMap, MAC_4_KEY)||IsKeyDown(theKeyMap, MAC_5_KEY)
+ ||IsKeyDown(theKeyMap, MAC_6_KEY)||IsKeyDown(theKeyMap, MAC_7_KEY)||IsKeyDown(theKeyMap, MAC_8_KEY)||IsKeyDown(theKeyMap, MAC_9_KEY)||IsKeyDown(theKeyMap, MAC_0_KEY)
+ ||IsKeyDown(theKeyMap, MAC_MINUS_KEY))){
+ int whichend;
+ if(IsKeyDown(theKeyMap, MAC_1_KEY))whichend=1;
+ if(IsKeyDown(theKeyMap, MAC_2_KEY))whichend=2;
+ if(IsKeyDown(theKeyMap, MAC_3_KEY))whichend=3;
+ if(IsKeyDown(theKeyMap, MAC_4_KEY))whichend=4;
+ if(IsKeyDown(theKeyMap, MAC_5_KEY))whichend=5;
+ if(IsKeyDown(theKeyMap, MAC_6_KEY))whichend=6;
+ if(IsKeyDown(theKeyMap, MAC_7_KEY))whichend=7;
+ if(IsKeyDown(theKeyMap, MAC_8_KEY))whichend=8;
+ if(IsKeyDown(theKeyMap, MAC_9_KEY))whichend=9;
+ if(IsKeyDown(theKeyMap, MAC_0_KEY))whichend=0;
+ if(IsKeyDown(theKeyMap, MAC_MINUS_KEY))whichend=-1;
+ if(whichend!=-1){
+ participantfocus[whichdialogue][indialogue]=whichend;
+ participantlocation[whichdialogue][whichend]=player[whichend].coords;
+ participantrotation[whichdialogue][whichend]=player[whichend].rotation;
+ }
+ if(whichend==-1){
+ participantfocus[whichdialogue][indialogue]=-1;
+ }
+ if(player[participantfocus[whichdialogue][indialogue]].dead){
+ indialogue=-1;
+ directing=0;
+ cameramode=0;
+ }
+ dialoguecamera[whichdialogue][indialogue]=viewer;
+ dialoguecamerarotation[whichdialogue][indialogue]=rotation;
+ dialoguecamerarotation2[whichdialogue][indialogue]=rotation2;
+ indialogue++;
+ if(indialogue<numdialogueboxes[whichdialogue]){
+ if(dialogueboxsound[whichdialogue][indialogue]!=0){
+ static float gLoc[3];
+ static float vel[3];
+ XYZ temppos;
+ temppos=player[participantfocus[whichdialogue][indialogue]].coords;
+ temppos=temppos-viewer;
+ Normalise(&temppos);
+ temppos+=viewer;
+
+ gLoc[0]=temppos.x;
+ gLoc[1]=temppos.y;
+ gLoc[2]=temppos.z;vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ int whichsoundplay;
+ if(dialogueboxsound[whichdialogue][indialogue]==1)whichsoundplay=rabbitchitter;
+ if(dialogueboxsound[whichdialogue][indialogue]==2)whichsoundplay=rabbitchitter2;
+ if(dialogueboxsound[whichdialogue][indialogue]==3)whichsoundplay=rabbitpainsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==4)whichsoundplay=rabbitpain1sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==5)whichsoundplay=rabbitattacksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==6)whichsoundplay=rabbitattack2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==7)whichsoundplay=rabbitattack3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==8)whichsoundplay=rabbitattack4sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==9)whichsoundplay=growlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==10)whichsoundplay=growl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==11)whichsoundplay=snarlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==12)whichsoundplay=snarl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==13)whichsoundplay=barksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==14)whichsoundplay=bark2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==15)whichsoundplay=bark3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==16)whichsoundplay=barkgrowlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-1)whichsoundplay=fireendsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-2)whichsoundplay=firestartsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-3)whichsoundplay=consolesuccesssound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-4)whichsoundplay=consolefailsound;
+ PlaySoundEx( whichsoundplay, samp[whichsoundplay], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsoundplay], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsoundplay], 256);
+ FSOUND_SetPaused(channels[whichsoundplay], FALSE);
+ }
+ }
+
+ for(j=0;j<numplayers;j++){
+ participantfacing[whichdialogue][indialogue][j]=participantfacing[whichdialogue][indialogue-1][j];
+ }
+
+ endkeydown=1;
+ }
+ if((IsKeyDown(theKeyMap, MAC_NUMPAD_1_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_2_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_3_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_4_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_5_KEY)
+ ||IsKeyDown(theKeyMap, MAC_NUMPAD_6_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_7_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_8_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_9_KEY)||IsKeyDown(theKeyMap, MAC_NUMPAD_0_KEY)
+ )){
+ int whichend;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_1_KEY))whichend=1;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_2_KEY))whichend=2;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_3_KEY))whichend=3;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_4_KEY))whichend=4;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_5_KEY))whichend=5;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_6_KEY))whichend=6;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_7_KEY))whichend=7;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_8_KEY))whichend=8;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_9_KEY))whichend=9;
+ if(IsKeyDown(theKeyMap, MAC_NUMPAD_0_KEY))whichend=0;
+ participantfacing[whichdialogue][indialogue][whichend]=facing;
+ }
+ if(!IsKeyDown(theKeyMap, MAC_1_KEY)&&!IsKeyDown(theKeyMap, MAC_2_KEY)&&!IsKeyDown(theKeyMap, MAC_3_KEY)&&!IsKeyDown(theKeyMap, MAC_4_KEY)&&!IsKeyDown(theKeyMap, MAC_5_KEY)
+ &&!IsKeyDown(theKeyMap, MAC_6_KEY)&&!IsKeyDown(theKeyMap, MAC_7_KEY)&&!IsKeyDown(theKeyMap, MAC_8_KEY)&&!IsKeyDown(theKeyMap, MAC_9_KEY)&&!IsKeyDown(theKeyMap, MAC_0_KEY)
+ &&!IsKeyDown(theKeyMap, MAC_MINUS_KEY)){
+ endkeydown=0;
+ }
+ if(indialogue>=numdialogueboxes[whichdialogue]){
+ indialogue=-1;
+ directing=0;
+ cameramode=0;
+ }
+ }
+ if(!directing){
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ viewer=dialoguecamera[whichdialogue][indialogue];
+ if(viewer.y<terrain.getHeight(viewer.x,viewer.z)+.1){
+ viewer.y=terrain.getHeight(viewer.x,viewer.z)+.1;
+ }
+ rotation=dialoguecamerarotation[whichdialogue][indialogue];
+ rotation2=dialoguecamerarotation2[whichdialogue][indialogue];
+ if(dialoguetime>0.5)
+ if((!endkeydown&&(IsKeyDown(theKeyMap, MAC_1_KEY)||IsKeyDown(theKeyMap, MAC_2_KEY)||IsKeyDown(theKeyMap, MAC_3_KEY)||IsKeyDown(theKeyMap, MAC_4_KEY)||IsKeyDown(theKeyMap, MAC_5_KEY)
+ ||IsKeyDown(theKeyMap, MAC_6_KEY)||IsKeyDown(theKeyMap, MAC_7_KEY)||IsKeyDown(theKeyMap, MAC_8_KEY)||IsKeyDown(theKeyMap, MAC_9_KEY)||IsKeyDown(theKeyMap, MAC_0_KEY)
+ ||IsKeyDown(theKeyMap, MAC_MINUS_KEY)))||(IsKeyDown(theKeyMap, attackkey)&&!oldbuttondialogue)){
+ indialogue++;
+ endkeydown=1;
+ if(indialogue<numdialogueboxes[whichdialogue]){
+ if(dialogueboxsound[whichdialogue][indialogue]!=0){
+ static float gLoc[3];
+ static float vel[3];
+ XYZ temppos;
+ temppos=player[participantfocus[whichdialogue][indialogue]].coords;
+ temppos=temppos-viewer;
+ Normalise(&temppos);
+ temppos+=viewer;
+
+ gLoc[0]=temppos.x;
+ gLoc[1]=temppos.y;
+ gLoc[2]=temppos.z;vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ int whichsoundplay;
+ if(dialogueboxsound[whichdialogue][indialogue]==1)whichsoundplay=rabbitchitter;
+ if(dialogueboxsound[whichdialogue][indialogue]==2)whichsoundplay=rabbitchitter2;
+ if(dialogueboxsound[whichdialogue][indialogue]==3)whichsoundplay=rabbitpainsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==4)whichsoundplay=rabbitpain1sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==5)whichsoundplay=rabbitattacksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==6)whichsoundplay=rabbitattack2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==7)whichsoundplay=rabbitattack3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==8)whichsoundplay=rabbitattack4sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==9)whichsoundplay=growlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==10)whichsoundplay=growl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==11)whichsoundplay=snarlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==12)whichsoundplay=snarl2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==13)whichsoundplay=barksound;
+ if(dialogueboxsound[whichdialogue][indialogue]==14)whichsoundplay=bark2sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==15)whichsoundplay=bark3sound;
+ if(dialogueboxsound[whichdialogue][indialogue]==16)whichsoundplay=barkgrowlsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-1)whichsoundplay=fireendsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-2)whichsoundplay=firestartsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-3)whichsoundplay=consolesuccesssound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-4)whichsoundplay=consolefailsound;
+ if(dialogueboxsound[whichdialogue][indialogue]==-6)whichsoundplay=alarmsound;
+ if(dialogueboxsound[whichdialogue][indialogue]!=-5){
+ PlaySoundEx( whichsoundplay, samp[whichsoundplay], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsoundplay], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsoundplay], 256);
+ FSOUND_SetPaused(channels[whichsoundplay], FALSE);
+ }
+ if(dialogueboxsound[whichdialogue][indialogue]==-5){
+ hotspot[numhotspots]=player[0].coords;
+ hotspotsize[numhotspots]=10;
+ hotspottype[numhotspots]=-1;
+
+ numhotspots++;
+ }
+ if(dialogueboxsound[whichdialogue][indialogue]==-6){
+ hostile=1;
+ }
+
+ if(player[participantfocus[whichdialogue][indialogue]].dead){
+ indialogue=-1;
+ directing=0;
+ cameramode=0;
+ }
+ }
+ }
+ }
+ if(!IsKeyDown(theKeyMap, MAC_1_KEY)&&!IsKeyDown(theKeyMap, MAC_2_KEY)&&!IsKeyDown(theKeyMap, MAC_3_KEY)&&!IsKeyDown(theKeyMap, MAC_4_KEY)&&!IsKeyDown(theKeyMap, MAC_5_KEY)
+ &&!IsKeyDown(theKeyMap, MAC_6_KEY)&&!IsKeyDown(theKeyMap, MAC_7_KEY)&&!IsKeyDown(theKeyMap, MAC_8_KEY)&&!IsKeyDown(theKeyMap, MAC_9_KEY)&&!IsKeyDown(theKeyMap, MAC_0_KEY)
+ &&!IsKeyDown(theKeyMap, MAC_MINUS_KEY)){
+ endkeydown=0;
+ }
+ if(indialogue>=numdialogueboxes[whichdialogue]){
+ indialogue=-1;
+ directing=0;
+ cameramode=0;
+ if(dialoguetype[whichdialogue]>19&&dialoguetype[whichdialogue]<30){
+ hostile=1;
+ }
+ if(dialoguetype[whichdialogue]>29&&dialoguetype[whichdialogue]<40){
+ windialogue=1;
+ }
+ if(dialoguetype[whichdialogue]>49&&dialoguetype[whichdialogue]<60){
+ hostile=1;
+ for(i=1;i<numplayers;i++){
+ player[i].aitype = attacktypecutoff;
+ }
+ }
+ }
+ }
+ }
+
+ if(!IsKeyDown(theKeyMap, attackkey))oldbuttondialogue=0;
+ else oldbuttondialogue=1;
+
+ static float keyrefreshdelay=0,bigrefreshdelay=0;
+
+ //Net updates
+
+ /*keyrefreshdelay-=multiplier;
+ bigrefreshdelay-=multiplier;
+
+ if(keyrefreshdelay<=0){
+ static int concat[4];
+
+ concat[0]=player[0].forwardkeydown;
+ concat[0]=concat[0]*2+player[0].forwardstogglekeydown;
+ concat[0]=concat[0]*2+player[0].rightkeydown;
+ concat[0]=concat[0]*2+player[0].leftkeydown;
+ concat[0]=concat[0]*2+player[0].backkeydown;
+ concat[0]=concat[0]*2+player[0].jumpkeydown;
+ concat[0]=concat[0]*2+player[0].jumptogglekeydown;
+ concat[0]=concat[0]*2+player[0].crouchkeydown;
+
+ concat[1]=player[0].crouchtogglekeydown;
+ concat[1]=concat[1]*2+player[0].drawkeydown;
+ concat[1]=concat[1]*2+player[0].drawtogglekeydown;
+ concat[1]=concat[1]*2+player[0].throwkeydown;
+ concat[1]=concat[1]*2+player[0].throwtogglekeydown;
+ concat[1]=concat[1]*2+player[0].attackkeydown;
+
+ //concat[2]=(char)((int)(rotation/2)%180);
+
+ //concat[3]=(char)((int)(rotation2/2)%180);
+
+ chatname[0]=concat[0]-128;
+ chatname[1]=concat[1]-128;
+ //chatname[2]=concat[2]-128;
+ //chatname[3]=concat[3]-128;
+ int temppoint=2;
+ memcpy(chatname+temppoint,&rotation,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&rotation2,sizeof(float));
+ temppoint+=sizeof(float);
+
+ chatname[temppoint]='\0';
+
+ //if(!ishost)NetworkSendPlayerMessage( chatname, kMessageType_Keys );
+ //if(ishost)NetworkSendPlayerRelayMessage( chatname, kMessageType_Keys );
+ //keyrefreshdelay=.01;
+ keyrefreshdelay=.03;
+ }
+
+ if(bigrefreshdelay<=0){
+ for(i=0;i<1;i++){
+ /*int temppoint=0;
+ memcpy(chatname+temppoint,&i,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].coords.x,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].coords.y,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].coords.z,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].damage,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].target,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].targetanimation,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].currentanimation,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].velocity.x,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].velocity.y,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].velocity.z,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].targetframe,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].currentframe,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].rotation,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].targetrotation,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].bloodloss,sizeof(float));
+ temppoint+=sizeof(float);
+ memcpy(chatname+temppoint,&player[i].weaponactive,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].num_weapons,sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].weaponids[0],sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].weaponids[1],sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].weaponids[2],sizeof(int));
+ temppoint+=sizeof(int);
+ memcpy(chatname+temppoint,&player[i].weaponids[3],sizeof(int));
+ temppoint+=sizeof(int);
+ chatname[temppoint]='\0';
+
+ sprintf (chatname, "%d %f %f %f %f %f %d %d %f %f %f %d %d %f %f %f",i,player[i].coords.x,player[i].coords.y,player[i].coords.z,player[i].damage,player[i].target, player[i].targetanimation, player[i].currentanimation, player[i].velocity.x, player[i].velocity.y, player[i].velocity.z, player[i].targetframe, player[i].currentframe, player[i].rotation, player[i].targetrotation);
+ //if(ishost)NetworkSendPlayerRelayMessage( chatname, kMessageType_PlayerState );
+ //else NetworkSendPlayerMessage( chatname, kMessageType_PlayerState );
+
+ sprintf (chatname, "%d %f %d %d %d %d %d %d %d %d %f",i,player[i].bloodloss, player[i].weaponactive, player[i].num_weapons, player[i].weaponids[0], player[i].weaponids[1], player[i].weaponids[2], player[i].weaponids[3],player[i].dead,player[i].skeleton.free,player[i].permanentdamage);
+
+ //if(ishost)NetworkSendPlayerRelayMessage( chatname, kMessageType_PlayerStateMisc );
+ //else NetworkSendPlayerMessage( chatname, kMessageType_PlayerStateMisc );
+ }
+ //bigrefreshdelay=.02;
+ bigrefreshdelay=.1;
+ }
+ }*/
+
+ if(!player[0].jumpkeydown){
+ player[0].jumptogglekeydown=0;
+ }
+ if(player[0].jumpkeydown&&player[0].targetanimation!=jumpupanim&&player[0].targetanimation!=jumpdownanim&&!player[0].isFlip())player[0].jumptogglekeydown=1;
+
+
+ dialoguetime+=multiplier;
+ skybox.cloudmove+=multiplier;
+ hawkrotation+=multiplier*25;
+ realhawkcoords=0;
+ realhawkcoords.x=25;
+ realhawkcoords=DoRotation(realhawkcoords,0,hawkrotation,0)+hawkcoords;
+ hawkcalldelay-=multiplier/2;
+
+ if(hawkcalldelay<=0)
+ {
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=realhawkcoords.x;
+ gLoc[1]=realhawkcoords.y;
+ gLoc[2]=realhawkcoords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( hawksound, samp[hawksound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[hawksound], gLoc, vel);
+ FSOUND_SetVolume(channels[hawksound], 128);
+ FSOUND_SetPaused(channels[hawksound], FALSE);
+
+ hawkcalldelay=16+abs(Random()%8);
+ }
+ static float temptexdetail;
+
+
+ if(IsKeyDown(theKeyMap, MAC_H_KEY)&&debugmode){
+ player[0].damagetolerance=200000;
+ player[0].damage=0;
+ player[0].burnt=0;
+ player[0].permanentdamage=0;
+ player[0].superpermanentdamage=0;
+ /*
+ int whichchar;
+ whichchar = abs(Random()%7);
+ registrationname[whichchar]+=1;
+ */
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_J_KEY)&&!envtogglekeydown&&debugmode){
+ environment++;
+ if(environment>2)environment=0;
+ Setenvironment(environment);
+
+ envtogglekeydown=1;
+ }
+
+
+ if(!IsKeyDown(theKeyMap, MAC_J_KEY)){
+ envtogglekeydown=0;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_C_KEY)&&!cameratogglekeydown&&debugmode){
+ cameramode=1-cameramode;
+ cameratogglekeydown=1;
+ }
+
+ if(!IsKeyDown(theKeyMap, MAC_C_KEY)){
+ cameratogglekeydown=0;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_X_KEY)&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!detailtogglekeydown&&debugmode){
+ if(player[0].num_weapons>0){
+ if(weapons.type[player[0].weaponids[0]]==sword)weapons.type[player[0].weaponids[0]]=staff;
+ else if(weapons.type[player[0].weaponids[0]]==staff)weapons.type[player[0].weaponids[0]]=knife;
+ else weapons.type[player[0].weaponids[0]]=sword;
+ if(weapons.type[player[0].weaponids[0]]==sword){
+ weapons.mass[player[0].weaponids[0]]=1.5;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[0].weaponids[0]]==staff){
+ weapons.mass[player[0].weaponids[0]]=2;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=1.5;
+ }
+
+ if(weapons.type[player[0].weaponids[0]]==knife){
+ weapons.mass[player[0].weaponids[0]]=1;
+ weapons.tipmass[player[0].weaponids[0]]=1.2;
+ weapons.length[player[0].weaponids[0]]=.25;
+ }
+ }
+
+ /*for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==treeleavestype){
+ for(j=0;j<objects.numobjects;j++){
+ if(objects.type[j]==treetrunktype)
+ if(findDistancefast(&objects.position[i],&objects.position[j])<.5)
+ objects.scale[i]=objects.scale[j];
+ }
+ }
+ }*/
+ detailtogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_X_KEY)&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!detailtogglekeydown&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closest!=-1){
+ if(player[closest].num_weapons)
+ {
+ if(weapons.type[player[closest].weaponids[0]]==sword)weapons.type[player[closest].weaponids[0]]=staff;
+ else if(weapons.type[player[closest].weaponids[0]]==staff)weapons.type[player[closest].weaponids[0]]=knife;
+ else weapons.type[player[closest].weaponids[0]]=sword;
+ if(weapons.type[player[closest].weaponids[0]]==sword){
+ weapons.mass[player[closest].weaponids[0]]=1.5;
+ weapons.tipmass[player[closest].weaponids[0]]=1;
+ weapons.length[player[closest].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[0].weaponids[0]]==staff){
+ weapons.mass[player[0].weaponids[0]]=2;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=1.5;
+ }
+ if(weapons.type[player[closest].weaponids[0]]==knife){
+ weapons.mass[player[closest].weaponids[0]]=1;
+ weapons.tipmass[player[closest].weaponids[0]]=1.2;
+ weapons.length[player[closest].weaponids[0]]=.25;
+ }
+ }
+ if(!player[closest].num_weapons)
+ {
+ player[closest].weaponids[0]=weapons.numweapons;
+ weapons.owner[weapons.numweapons]=closest;
+ weapons.type[weapons.numweapons]=knife;
+ weapons.damage[weapons.numweapons]=0;
+ weapons.numweapons++;
+ player[closest].num_weapons=1;
+ if(weapons.type[player[closest].weaponids[0]]==sword){
+ weapons.mass[player[closest].weaponids[0]]=1.5;
+ weapons.tipmass[player[closest].weaponids[0]]=1;
+ weapons.length[player[closest].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[closest].weaponids[0]]==knife){
+ weapons.mass[player[closest].weaponids[0]]=1;
+ weapons.tipmass[player[closest].weaponids[0]]=1.2;
+ weapons.length[player[closest].weaponids[0]]=.25;
+ }
+ }
+ }
+ detailtogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_U_KEY)&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+
+ player[closest].rotation+=multiplier*50;
+ player[closest].targetrotation=player[closest].rotation;
+ }
+
+
+ if(IsKeyDown(theKeyMap, MAC_O_KEY)&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(IsKeyDown(theKeyMap, MAC_CONTROL_KEY))closest=0;
+
+ if(closest!=-1){
+ player[closest].whichskin++;
+ if(player[closest].whichskin>9)player[closest].whichskin=0;
+ if(player[closest].whichskin>2&&player[closest].creature==wolftype)player[closest].whichskin=0;
+
+ if(player[closest].creature==rabbittype){
+ if(player[closest].whichskin==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==2){
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==3){
+ LoadTextureSave(":Data:Textures:Lynx.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==4){
+ LoadTextureSave(":Data:Textures:Otter.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==5){
+ LoadTextureSave(":Data:Textures:Opal.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==6){
+ LoadTextureSave(":Data:Textures:Sable.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==7){
+ LoadTextureSave(":Data:Textures:Chocolate.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==8){
+ LoadTextureSave(":Data:Textures:BW2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==9){
+ LoadTextureSave(":Data:Textures:WB2.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ }
+ if(player[closest].creature==wolftype){
+ k=abs(Random()%3);
+ if(player[closest].whichskin==0){
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==1){
+ LoadTextureSave(":Data:Textures:Darkwolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ else if(player[closest].whichskin==2){
+ LoadTextureSave(":Data:Textures:Snowwolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ }
+ }
+
+ if(player[closest].numclothes){
+ for(i=0;i<player[closest].numclothes;i++){
+ tintr=player[closest].clothestintr[i];
+ tintg=player[closest].clothestintg[i];
+ tintb=player[closest].clothestintb[i];
+ AddClothes((char *)player[closest].clothes[i],0,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+ player[closest].DoMipmaps(5,0,0,player[closest].skeleton.skinsize,player[closest].skeleton.skinsize);
+ }
+
+ detailtogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_O_KEY)&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closest!=-1){
+ if(player[closest].creature==wolftype){
+ headprop=player[closest].proportionhead.x/1.1;
+ bodyprop=player[closest].proportionbody.x/1.1;
+ armprop=player[closest].proportionarms.x/1.1;
+ legprop=player[closest].proportionlegs.x/1.1;
+ }
+
+ if(player[closest].creature==rabbittype){
+ headprop=player[closest].proportionhead.x/1.2;
+ bodyprop=player[closest].proportionbody.x/1.05;
+ armprop=player[closest].proportionarms.x/1.00;
+ legprop=player[closest].proportionlegs.x/1.1;
+ }
+
+
+ if(player[closest].creature==rabbittype){
+ player[closest].skeleton.id=closest;
+ player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf",(char *)":Data:Skeleton:Basic Figure Wolf Low",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Wolf.solid",(char *)":Data:Models:Wolf2.solid",(char *)":Data:Models:Wolf3.solid",(char *)":Data:Models:Wolf4.solid",(char *)":Data:Models:Wolf5.solid",(char *)":Data:Models:Wolf6.solid",(char *)":Data:Models:Wolf7.solid",(char *)":Data:Models:Wolflow.solid",(char *)":Data:Models:Belt.solid",0);
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[closest],&player[closest].skeleton.skinsize);
+ player[closest].whichskin=0;
+ player[closest].creature=wolftype;
+
+ player[closest].proportionhead=1.1;
+ player[closest].proportionbody=1.1;
+ player[closest].proportionarms=1.1;
+ player[closest].proportionlegs=1.1;
+ player[closest].proportionlegs.y=1.1;
+ player[closest].scale=.23*5*player[0].scale;
+
+ player[closest].damagetolerance=300;
+ }
+ else
+ {
+ player[closest].skeleton.id=closest;
+ player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ player[closest].whichskin=0;
+ player[closest].creature=rabbittype;
+
+ player[closest].proportionhead=1.2;
+ player[closest].proportionbody=1.05;
+ player[closest].proportionarms=1.00;
+ player[closest].proportionlegs=1.1;
+ player[closest].proportionlegs.y=1.05;
+ player[closest].scale=.2*5*player[0].scale;
+
+ player[closest].damagetolerance=200;
+ }
+
+ if(player[closest].creature==wolftype){
+ player[closest].proportionhead=1.1*headprop;
+ player[closest].proportionbody=1.1*bodyprop;
+ player[closest].proportionarms=1.1*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ }
+
+ if(player[closest].creature==rabbittype){
+ player[closest].proportionhead=1.2*headprop;
+ player[closest].proportionbody=1.05*bodyprop;
+ player[closest].proportionarms=1.00*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ player[closest].proportionlegs.y=1.05*legprop;
+ }
+
+ }
+ detailtogglekeydown=1;
+ }
+
+ if(!IsKeyDown(theKeyMap, MAC_X_KEY)){
+ detailtogglekeydown=0;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_B_KEY)&&!slomotogglekeydown&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&debugmode){
+ slomo=1-slomo;
+ slomodelay=1000;
+ slomotogglekeydown=1;
+ }
+
+
+ if(((IsKeyDown(theKeyMap, MAC_I_KEY)&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY))/*||buttons[1]*/)&&!explodetogglekeydown&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ XYZ flatfacing2,flatvelocity2;
+ XYZ blah;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(distance<144&&!player[i].headless)
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ blah = player[i].coords;
+ }
+ }
+
+ if(closest!=-1){
+ XYZ headspurtdirection;
+ int i = player[closest].skeleton.jointlabels[head];
+ for(k=0;k<player[closest].skeleton.num_joints; k++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ headspurtdirection=player[closest].skeleton.joints[player[closest].skeleton.jointlabels[head]].position-player[closest].skeleton.joints[player[closest].skeleton.jointlabels[neck]].position;
+ Normalise(&headspurtdirection);
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, .6, 1);
+ flatvelocity2+=headspurtdirection*8;
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2/2, 1,1,1, .16, 1);
+ }
+ sprites.MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=blah.x;
+ gLoc[1]=blah.y;
+ gLoc[2]=blah.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( splattersound, samp[splattersound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[splattersound], gLoc, vel);
+ FSOUND_SetVolume(channels[splattersound], 256);
+ FSOUND_SetPaused(channels[splattersound], FALSE);
+
+ PlaySoundEx( breaksound2, samp[breaksound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound2], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound2], 100);
+ FSOUND_SetPaused(channels[breaksound2], FALSE);
+
+ if(player[closest].skeleton.free==2)player[closest].skeleton.free=0;
+ player[closest].RagDoll(0);
+ player[closest].dead=2;
+ player[closest].headless=1;
+ player[closest].DoBloodBig(3,165);
+
+ camerashake+=.3;
+ }
+
+ explodetogglekeydown=1;
+ }
+
+ if(((IsKeyDown(theKeyMap, MAC_I_KEY)&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY))/*||buttons[2]*/)&&!explodetogglekeydown&&debugmode){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ XYZ flatfacing2,flatvelocity2;
+ XYZ blah;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(distance<144)
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ blah=player[i].coords;
+ }
+ }
+
+ if(closest!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=blah.x;
+ gLoc[1]=blah.y;
+ gLoc[2]=blah.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+
+ PlaySoundEx( splattersound, samp[splattersound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[splattersound], gLoc, vel);
+ FSOUND_SetVolume(channels[splattersound], 256);
+ FSOUND_SetPaused(channels[splattersound], FALSE);
+
+ PlaySoundEx( breaksound2, samp[breaksound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound2], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound2], 600);
+ FSOUND_SetPaused(channels[breaksound2], FALSE);
+
+ for(i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .3, 1);
+ sprites.MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
+ }
+
+ for(i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .4, 1);
+ }
+
+ for(i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
+ }
+
+ for(i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
+ }
+
+ XYZ temppos;
+ for(j=0;j<numplayers; j++){
+ if(j!=closest){
+ if(findDistancefast(&player[j].coords,&player[closest].coords)<25){
+ player[j].DoDamage((25-findDistancefast(&player[j].coords,&player[closest].coords))*60);
+ if(player[j].skeleton.free==2)player[j].skeleton.free=1;
+ player[j].skeleton.longdead=0;
+ player[j].RagDoll(0);
+ for(i=0;i<player[j].skeleton.num_joints; i++){
+ temppos=player[j].skeleton.joints[i].position+player[j].coords;
+ if(findDistancefast(&temppos,&player[closest].coords)<25){
+ flatvelocity2=temppos-player[closest].coords;
+ Normalise(&flatvelocity2);
+ player[j].skeleton.joints[i].velocity+=flatvelocity2*((20-findDistancefast(&temppos,&player[closest].coords))*20);
+ }
+ }
+ }
+ }
+ }
+
+ player[closest].DoDamage(10000);
+ player[closest].RagDoll(0);
+ player[closest].dead=2;
+ player[closest].coords=20;
+ player[closest].skeleton.free=2;
+
+ camerashake+=.6;
+
+ }
+
+ explodetogglekeydown=1;
+ }
+
+ if(!IsKeyDown(theKeyMap, MAC_I_KEY)){
+ explodetogglekeydown=0;
+ }
+
+ /*
+ if(IsKeyDown(theKeyMap, MAC_S_KEY)&&IsKeyDown(theKeyMap, MAC_COMMAND_KEY)&&!slomotogglekeydown){
+ FILE *tfile;
+ //tfile=fopen( ":Data:Maps:mapsave", "wb" );
+ if(whichlevel==0)tfile=fopen( ":Data:Maps:map1", "wb" );
+ else if(whichlevel==1)tfile=fopen( ":Data:Maps:map2", "wb" );
+ else if(whichlevel==2)tfile=fopen( ":Data:Maps:map3", "wb" );
+ else if(whichlevel==3)tfile=fopen( ":Data:Maps:map4", "wb" );
+ else if(whichlevel==4)tfile=fopen( ":Data:Maps:map5", "wb" );
+ else tfile=fopen( ":Data:Maps:mapsave", "wb" );
+
+ fwrite( &player[0].coords, 1, sizeof(XYZ), tfile );
+ fwrite( &player[0].rotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].targetrotation, 1, sizeof(float), tfile );
+ fwrite( &player[0].num_weapons, 1, sizeof(int), tfile );
+ for(j=0;j<player[0].num_weapons;j++){
+ fwrite( &weapons.type[player[0].weaponids[j]], 1, sizeof(int), tfile );
+ }
+ fwrite( &environment, 1, sizeof(int), tfile );
+
+ fwrite( &objects.numobjects, 1, sizeof(int), tfile );
+ fwrite( &objects.type, 1, sizeof(int)*objects.numobjects, tfile );
+ fwrite( &objects.rotation, 1, sizeof(float)*objects.numobjects, tfile );
+ fwrite( &objects.position, 1, sizeof(XYZ)*objects.numobjects, tfile );
+ fwrite( &objects.scale, 1, sizeof(float)*objects.numobjects, tfile );
+
+ fwrite( &numplayers, 1, sizeof(int), tfile );
+ if(numplayers>1&&numplayers<maxplayers)
+ for(i=1;i<numplayers;i++){
+ fwrite( &player[i].coords, 1, sizeof(XYZ), tfile );
+ fwrite( &player[i].num_weapons, 1, sizeof(int), tfile );
+ for(j=0;j<player[i].num_weapons;j++){
+ fwrite( &weapons.type[player[i].weaponids[j]], 1, sizeof(int), tfile );
+ }
+ if(player[i].numwaypoints<30){
+ fwrite( &player[i].numwaypoints, 1, sizeof(int), tfile );
+ fwrite( &player[i].waypoints, 1, sizeof(XYZ)*player[i].numwaypoints, tfile );
+ fwrite( &player[i].waypoint, 1, sizeof(int), tfile );
+ //fwrite( &player[i].jumppath, 1, sizeof(bool), tfile );
+ }
+ else{
+ player[i].numwaypoints=0;
+ player[i].waypoint=0;
+ fwrite( &player[i].numwaypoints, 1, sizeof(int), tfile );
+ fwrite( &player[i].waypoint, 1, sizeof(int), tfile );
+ fwrite( &player[i].waypoint, 1, sizeof(int), tfile );
+ }
+ }
+
+ fclose(tfile);
+
+ slomotogglekeydown=1;
+ }*/
+
+ if(!IsKeyDown(theKeyMap, MAC_B_KEY)&&!IsKeyDown(theKeyMap, MAC_F_KEY)&&!IsKeyDown(theKeyMap, MAC_K_KEY)&&!IsKeyDown(theKeyMap, MAC_S_KEY)){
+ slomotogglekeydown=0;
+ }
+
+
+ if(IsKeyDown(theKeyMap, MAC_F_KEY)&&!slomotogglekeydown&&debugmode){
+ player[0].onfire=1-player[0].onfire;
+ if(player[0].onfire){
+ player[0].CatchFire();
+ }
+ if(!player[0].onfire){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[0].coords.x;
+ gLoc[1]=player[0].coords.y;
+ gLoc[2]=player[0].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_SetPaused(channels[stream_firesound], TRUE);
+ }
+ slomotogglekeydown=1;
+ }
+ /*
+ if(IsKeyDown(theKeyMap, MAC_L_KEY)){
+ if(player[0].bleeding<=0)
+ player[0].DoBlood(1,255);
+ }*/
+
+
+ if(IsKeyDown(theKeyMap, MAC_DELETE_KEY)&&editorenabled&&!drawmodetogglekeydown&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0){
+ //player[closest]=player[numplayers-1];
+ //player[closest].skeleton=player[numplayers-1].skeleton;
+ numplayers--;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_DELETE_KEY)&&editorenabled&&!drawmodetogglekeydown&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(max_objects>1)
+ for(i=1;i<max_objects;i++){
+ distance=findDistancefast(&objects.position[i],&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0){
+ objects.position[closest].y-=500;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_M_KEY)&&!drawmodetogglekeydown&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&editorenabled&&debugmode){
+ //drawmode++;
+ //if(drawmode>2)drawmode=0;
+ if(objects.numobjects<max_objects-1){
+ XYZ boxcoords;
+ boxcoords.x=player[0].coords.x;
+ boxcoords.z=player[0].coords.z;
+ boxcoords.y=player[0].coords.y-3;
+ if(editortype==bushtype)boxcoords.y=player[0].coords.y-.5;
+ if(editortype==firetype)boxcoords.y=player[0].coords.y-.5;
+ //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
+ float temprotat,temprotat2;
+ temprotat=editorrotation;
+ temprotat2=editorrotation2;
+ if(temprotat<0||editortype==bushtype)temprotat=Random()%360;
+ if(temprotat2<0)temprotat2=Random()%360;
+
+ objects.MakeObject(editortype,boxcoords,(int)temprotat-((int)temprotat)%30,(int)temprotat2,editorsize);
+ if(editortype==treetrunktype)
+ objects.MakeObject(treeleavestype,boxcoords,Random()%360*(temprotat2<2)+(int)editorrotation-((int)editorrotation)%30,editorrotation2,editorsize);
+ }
+
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_P_KEY)&&!drawmodetogglekeydown&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)&&editorenabled){
+ if(numplayers<maxplayers-1){
+ player[numplayers].scale=.2*5*player[0].scale;
+ player[numplayers].creature=rabbittype;
+ player[numplayers].howactive=editoractive;
+ player[numplayers].skeleton.id=numplayers;
+ player[numplayers].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+
+ //texsize=512*512*3/texdetail/texdetail;
+ //if(!player[numplayers].loaded)player[numplayers].skeleton.skinText = new GLubyte[texsize];
+ //player[numplayers].skeleton.skinText.resize(texsize);
+
+ k=abs(Random()%2)+1;
+ if(k==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=0;
+ }
+ else if(k==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=1;
+ }
+ else {
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=2;
+ }
+
+ LoadTexture(":Data:Textures:Belt.png",&player[numplayers].skeleton.drawmodelclothes.textureptr,1,1);
+ player[numplayers].power=1;
+ player[numplayers].speedmult=1;
+ player[numplayers].currentanimation=bounceidleanim;
+ player[numplayers].targetanimation=bounceidleanim;
+ player[numplayers].currentframe=0;
+ player[numplayers].targetframe=1;
+ player[numplayers].target=0;
+ player[numplayers].bled=0;
+ player[numplayers].speed=1+(float)(Random()%100)/1000;
+
+ player[numplayers].targetrotation=player[0].targetrotation;
+ player[numplayers].rotation=player[0].rotation;
+
+ player[numplayers].velocity=0;
+ player[numplayers].coords=player[0].coords;
+ player[numplayers].oldcoords=player[numplayers].coords;
+ player[numplayers].realoldcoords=player[numplayers].coords;
+
+ player[numplayers].id=numplayers;
+ player[numplayers].skeleton.id=numplayers;
+ player[numplayers].updatedelay=0;
+ player[numplayers].normalsupdatedelay=0;
+
+ player[numplayers].aitype=passivetype;
+ player[numplayers].aitarget=0;
+
+ if(player[0].creature==wolftype){
+ headprop=player[0].proportionhead.x/1.1;
+ bodyprop=player[0].proportionbody.x/1.1;
+ armprop=player[0].proportionarms.x/1.1;
+ legprop=player[0].proportionlegs.x/1.1;
+ }
+
+ if(player[0].creature==rabbittype){
+ headprop=player[0].proportionhead.x/1.2;
+ bodyprop=player[0].proportionbody.x/1.05;
+ armprop=player[0].proportionarms.x/1.00;
+ legprop=player[0].proportionlegs.x/1.1;
+ }
+
+ if(player[numplayers].creature==wolftype){
+ player[numplayers].proportionhead=1.1*headprop;
+ player[numplayers].proportionbody=1.1*bodyprop;
+ player[numplayers].proportionarms=1.1*armprop;
+ player[numplayers].proportionlegs=1.1*legprop;
+ }
+
+ if(player[numplayers].creature==rabbittype){
+ player[numplayers].proportionhead=1.2*headprop;
+ player[numplayers].proportionbody=1.05*bodyprop;
+ player[numplayers].proportionarms=1.00*armprop;
+ player[numplayers].proportionlegs=1.1*legprop;
+ player[numplayers].proportionlegs.y=1.05*legprop;
+ }
+
+ player[numplayers].headless=0;
+ player[numplayers].onfire=0;
+
+ if(cellophane){
+ player[numplayers].proportionhead.z=0;
+ player[numplayers].proportionbody.z=0;
+ player[numplayers].proportionarms.z=0;
+ player[numplayers].proportionlegs.z=0;
+ }
+
+ player[numplayers].tempanimation.Load((char *)":Data:Animations:Tempanim",0,0);
+
+ player[numplayers].damagetolerance=200;
+
+ player[numplayers].protectionhead=player[0].protectionhead;
+ player[numplayers].protectionhigh=player[0].protectionhigh;
+ player[numplayers].protectionlow=player[0].protectionlow;
+ player[numplayers].armorhead=player[0].armorhead;
+ player[numplayers].armorhigh=player[0].armorhigh;
+ player[numplayers].armorlow=player[0].armorlow;
+ player[numplayers].metalhead=player[0].metalhead;
+ player[numplayers].metalhigh=player[0].metalhigh;
+ player[numplayers].metallow=player[0].metallow;
+
+ player[numplayers].immobile=player[0].immobile;
+
+ player[numplayers].numclothes=player[0].numclothes;
+ if(player[numplayers].numclothes)
+ for(i=0;i<player[numplayers].numclothes;i++){
+ strcpy(player[numplayers].clothes[i], player[0].clothes[i]);
+ player[numplayers].clothestintr[i]=player[0].clothestintr[i];
+ player[numplayers].clothestintg[i]=player[0].clothestintg[i];
+ player[numplayers].clothestintb[i]=player[0].clothestintb[i];
+ tintr=player[numplayers].clothestintr[i];
+ tintg=player[numplayers].clothestintg[i];
+ tintb=player[numplayers].clothestintb[i];
+ AddClothes((char *)player[numplayers].clothes[i],0,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ }
+ if(player[numplayers].numclothes){
+ player[numplayers].DoMipmaps(5,0,0,player[numplayers].skeleton.skinsize,player[numplayers].skeleton.skinsize);
+ }
+
+ player[numplayers].power=player[0].power;
+ player[numplayers].speedmult=player[0].speedmult;
+
+ player[numplayers].damage=0;
+ player[numplayers].permanentdamage=0;
+ player[numplayers].superpermanentdamage=0;
+ player[numplayers].deathbleeding=0;
+ player[numplayers].bleeding=0;
+ player[numplayers].numwaypoints=0;
+ player[numplayers].waypoint=0;
+ player[numplayers].jumppath=0;
+ player[numplayers].weaponstuck=-1;
+ player[numplayers].weaponactive=-1;
+ player[numplayers].num_weapons=0;
+ player[numplayers].bloodloss=0;
+ player[numplayers].dead=0;
+
+ player[numplayers].loaded=1;
+
+ numplayers++;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_P_KEY)&&!drawmodetogglekeydown&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&editorenabled){
+ if(player[numplayers-1].numwaypoints<90){
+ player[numplayers-1].waypoints[player[numplayers-1].numwaypoints]=player[0].coords;
+ player[numplayers-1].waypointtype[player[numplayers-1].numwaypoints]=editorpathtype;
+ player[numplayers-1].numwaypoints++;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_P_KEY)&&!drawmodetogglekeydown&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)&&editorenabled){
+ if(numpathpoints<30){
+ bool connected,alreadyconnected;
+ connected=0;
+ if(numpathpoints>1)
+ for(i=0;i<numpathpoints;i++){
+ if(findDistancefast(&pathpoint[i],&player[0].coords)<.5&&i!=pathpointselected&&!connected){
+ alreadyconnected=0;
+ for(j=0;j<numpathpointconnect[pathpointselected];j++){
+ if(pathpointconnect[pathpointselected][j]==i)alreadyconnected=1;
+ }
+ if(!alreadyconnected){
+ numpathpointconnect[pathpointselected]++;
+ connected=1;
+ pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=i;
+ }
+ }
+ }
+ if(!connected){
+ numpathpoints++;
+ pathpoint[numpathpoints-1]=player[0].coords;
+ numpathpointconnect[numpathpoints-1]=0;
+ if(numpathpoints>1&&pathpointselected!=-1){
+ numpathpointconnect[pathpointselected]++;
+ pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=numpathpoints-1;
+ }
+ pathpointselected=numpathpoints-1;
+ }
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_PERIOD_KEY)&&!drawmodetogglekeydown&&editorenabled){
+ pathpointselected++;
+ if(pathpointselected>=numpathpoints)pathpointselected=-1;
+ drawmodetogglekeydown=1;
+ }
+ if(IsKeyDown(theKeyMap, MAC_COMMA_KEY)&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!drawmodetogglekeydown&&editorenabled){
+ pathpointselected--;
+ if(pathpointselected<=-2)pathpointselected=numpathpoints-1;
+ drawmodetogglekeydown=1;
+ }
+ if(IsKeyDown(theKeyMap, MAC_COMMA_KEY)&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!drawmodetogglekeydown&&editorenabled){
+ if(pathpointselected!=-1){
+ numpathpoints--;
+ pathpoint[pathpointselected]=pathpoint[numpathpoints];
+ numpathpointconnect[pathpointselected]=numpathpointconnect[numpathpoints];
+ for(i=0;i<numpathpointconnect[pathpointselected];i++){
+ pathpointconnect[pathpointselected][i]=pathpointconnect[numpathpoints][i];
+ }
+ for(i=0;i<numpathpoints;i++){
+ for(j=0;j<numpathpointconnect[i];j++){
+ if(pathpointconnect[i][j]==pathpointselected){
+ pathpointconnect[i][j]=pathpointconnect[i][numpathpointconnect[i]-1];
+ numpathpointconnect[i]--;
+ }
+ if(pathpointconnect[i][j]==numpathpoints){
+ pathpointconnect[i][j]=pathpointselected;
+ }
+ }
+ }
+ pathpointselected=numpathpoints-1;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_M_KEY)&&!drawmodetogglekeydown&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&debugmode){
+ editorenabled=1-editorenabled;
+ if(editorenabled){
+ player[0].damagetolerance=100000;
+ player[0].damage=0;
+ player[0].superpermanentdamage=0;
+ player[0].bloodloss=0;
+ player[0].deathbleeding=0;
+ }
+ if(!editorenabled){
+ player[0].damagetolerance=200;
+ player[0].damage=0;
+ player[0].permanentdamage=0;
+ player[0].superpermanentdamage=0;
+ player[0].bloodloss=0;
+ player[0].deathbleeding=0;
+ }
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_LEFT_KEY)&&!drawmodetogglekeydown&&editorenabled&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editortype--;
+ if(editortype==treeleavestype||editortype==10)editortype--;
+ if(editortype<0)editortype=firetype;
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_RIGHT_KEY)&&!drawmodetogglekeydown&&editorenabled&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editortype++;
+ if(editortype==treeleavestype||editortype==10)editortype++;
+ if(editortype>firetype)editortype=0;
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_LEFT_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorrotation-=multiplier*100;
+ if(editorrotation<-.01)editorrotation=-.01;
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_RIGHT_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorrotation+=multiplier*100;
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_UP_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorsize+=multiplier;
+ drawmodetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_DOWN_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorsize-=multiplier;
+ if(editorsize<.1)editorsize=.1;
+ drawmodetogglekeydown=1;
+ }
+
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_LEFT_KEY)&&!drawmodetogglekeydown&&editorenabled&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapradius-=multiplier*10;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_RIGHT_KEY)&&!drawmodetogglekeydown&&editorenabled&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapradius+=multiplier*10;
+ }
+ /*
+ if(IsKeyDown(theKeyMap, MAC_ARROW_LEFT_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapcenter.x+=multiplier*20;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_RIGHT_KEY)&&editorenabled&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapcenter.x-=multiplier*20;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_UP_KEY)&&editorenabled&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapcenter.z+=multiplier*20;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_DOWN_KEY)&&editorenabled&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ mapcenter.z-=multiplier*20;
+ }
+ */
+ if(IsKeyDown(theKeyMap, MAC_ARROW_UP_KEY)&&editorenabled&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorrotation2+=multiplier*100;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_ARROW_DOWN_KEY)&&editorenabled&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)){
+ editorrotation2-=multiplier*100;
+ if(editorrotation2<-.01)editorrotation2=-.01;
+ }
+ if(IsKeyDown(theKeyMap, MAC_DELETE_KEY)&&editorenabled&&objects.numobjects&&!drawmodetogglekeydown&&!IsKeyDown(theKeyMap, MAC_SHIFT_KEY)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ for(i=0;i<objects.numobjects;i++){
+ distance=findDistancefast(&objects.position[i],&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0)objects.DeleteObject(closest);
+ drawmodetogglekeydown=1;
+ }
+
+
+ if(!IsKeyDown(theKeyMap, MAC_M_KEY)&&!IsKeyDown(theKeyMap, MAC_ARROW_LEFT_KEY)&&!IsKeyDown(theKeyMap, MAC_COMMA_KEY)&&!IsKeyDown(theKeyMap, MAC_PERIOD_KEY)&&!IsKeyDown(theKeyMap, MAC_ARROW_RIGHT_KEY)&&!IsKeyDown(theKeyMap, MAC_DELETE_KEY)&&!IsKeyDown(theKeyMap, MAC_P_KEY)){
+ drawmodetogglekeydown=0;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_N_KEY)&&!IsKeyDown(theKeyMap, MAC_CONTROL_KEY)&&!texturesizetogglekeydown&&debugmode){
+ //if(!player[0].skeleton.free)player[0].damage+=500;
+ player[0].RagDoll(0);
+ //player[0].spurt=1;
+ //player[0].DoDamage(1000);
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[0].coords.x;
+ gLoc[1]=player[0].coords.y;
+ gLoc[2]=player[0].coords.z;
+ vel[0]=player[0].velocity.x;
+ vel[1]=player[0].velocity.y;
+ vel[2]=player[0].velocity.z;
+ PlaySoundEx( whooshsound, samp[whooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshsound], 128);
+ FSOUND_SetPaused(channels[whooshsound], FALSE);
+ //FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ texturesizetogglekeydown=1;
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_N_KEY)&&IsKeyDown(theKeyMap, MAC_CONTROL_KEY)&&!texturesizetogglekeydown&&debugmode){
+
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==treeleavestype){
+ objects.scale[i]*=.9;
+ }
+ }
+ texturesizetogglekeydown=1;
+ }
+
+ static XYZ relative;
+ static int randattack;
+ //Attack
+ static bool playerrealattackkeydown=0;
+
+ if(!buttons[0])oldbutton=0;
+ if(!IsKeyDown(theKeyMap, attackkey))oldattackkey=0;
+ if(oldattackkey)player[0].attackkeydown=0;
+ if(oldattackkey)playerrealattackkeydown=0;
+ if(!oldattackkey)playerrealattackkeydown=IsKeyDown(theKeyMap, attackkey);
+ if((player[0].parriedrecently<=0||player[0].weaponactive==-1)&&(!oldattackkey||(realthreat&&player[0].lastattack!=swordslashanim&&player[0].lastattack!=knifeslashstartanim&&player[0].lastattack!=staffhitanim&&player[0].lastattack!=staffspinhitanim)))player[0].attackkeydown=IsKeyDown(theKeyMap, attackkey);
+ if(IsKeyDown(theKeyMap, attackkey)&&!oldattackkey&&!player[0].backkeydown){
+ for(k=0;k<numplayers;k++){
+ if((player[k].targetanimation==swordslashanim||player[k].targetanimation==staffhitanim||player[k].targetanimation==staffspinhitanim)&&player[0].currentanimation!=dodgebackanim&&!player[k].skeleton.free)
+ player[k].Reverse();
+ }
+ }
+
+ if(!hostile||indialogue!=-1)player[0].attackkeydown=0;
+
+ for(k=0;k<numplayers;k++){
+ if(indialogue!=-1)player[k].attackkeydown=0;
+ if(player[k].targetanimation!=rabbitrunninganim&&player[k].targetanimation!=wolfrunninganim){
+ if(player[k].aitype!=playercontrolled)player[k].victim=&player[0];
+ if(player[k].attackkeydown&&player[k].jumppower<=1&&player[k].backkeydown&&player[k].targetanimation!=backhandspringanim&&(player[k].isIdle()||player[k].isStop()||player[k].isRun()||player[k].targetanimation==walkanim)){
+ player[k].jumppower-=2;
+ }
+ if(player[k].attackkeydown&&player[k].jumppower>1&&player[k].backkeydown&&player[k].targetanimation!=backhandspringanim&&(player[k].isIdle()||player[k].isStop()||player[k].isRun()||player[k].targetanimation==walkanim)){
+ for(i=0;i<numplayers;i++){
+ if(i==k)i++;
+ if(player[i].targetanimation==swordslashanim||player[i].targetanimation==knifeslashstartanim||player[i].targetanimation==staffhitanim||player[i].targetanimation==staffspinhitanim)
+ if(findDistancefast(&player[k].coords,&player[i].coords)<6.5&&!player[i].skeleton.free){
+ player[k].targetanimation=dodgebackanim;
+ player[k].target=0;
+ player[k].targetframe=0;
+ rotatetarget=player[i].coords-player[k].coords;
+ Normalise(&rotatetarget);
+ player[k].targetrotation=-asin(0-rotatetarget.x);
+ player[k].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[k].targetrotation=180-player[k].targetrotation;
+
+ player[k].targettilt2=-asin(rotatetarget.y)*360/6.28;
+ }
+ }
+ if(player[k].targetanimation!=dodgebackanim){
+ if(k==0)numflipped++;
+ player[k].targetanimation=backhandspringanim;
+ player[k].target=0;
+ player[k].targetframe=0;
+ player[k].targetrotation=-rotation+180;
+ if(player[k].leftkeydown)player[k].targetrotation-=45;
+ if(player[k].rightkeydown)player[k].targetrotation+=45;
+ player[k].rotation=player[k].targetrotation;
+ player[k].jumppower-=2;
+ }
+ }
+ if(player[k].attackkeydown&&!animation[player[k].targetanimation].attack&&!player[k].backkeydown&&(player[k].isIdle()||player[k].isRun()||player[k].targetanimation==walkanim||player[k].targetanimation==sneakanim||player[k].isCrouch())){
+ player[k].hasvictim=0;
+ if(numplayers>1)
+ for(i=0;i<numplayers;i++){
+ if(i==k)i++;
+ if(!player[k].hasvictim)
+ if((k==0||i==0)&&i!=k&&i<numplayers&&k<numplayers&&animation[player[k].targetanimation].attack!=reversal){
+ if(findDistancefast(&player[k].coords,&player[i].coords)<4.5&&!player[i].skeleton.free&&player[i].howactive<typedead1&&player[i].targetanimation!=jumpreversedanim&&player[i].targetanimation!=rabbitkickreversedanim&&player[i].targetanimation!=rabbitkickanim&&player[k].targetanimation!=rabbitkickanim&&player[i].targetanimation!=getupfrombackanim&&(player[i].targetanimation!=staggerbackhighanim&&(player[i].targetanimation!=staggerbackhardanim||animation[staggerbackhardanim].label[player[i].targetframe]==6))&&player[i].targetanimation!=jumpdownanim&&player[i].targetanimation!=jumpupanim&&player[i].targetanimation!=getupfromfrontanim){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ if(player[k].aitype==playercontrolled){
+ if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&player[k].crouchkeydown&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=sweepanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<1.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].forwardkeydown&&!player[k].leftkeydown&&!player[k].rightkeydown&&!player[k].crouchkeydown&&player[k].weaponactive==-1&&!reversaltrain)player[k].targetanimation=winduppunchanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].forwardkeydown&&!player[k].leftkeydown&&!player[k].rightkeydown&&!player[k].crouchkeydown&&player[k].weaponactive==-1)player[k].targetanimation=upunchanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&player[k].weaponactive!=-1&&player[i].staggerdelay>0&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife&&player[i].bloodloss>player[i].damagetolerance/2)player[k].targetanimation=knifefollowanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].forwardkeydown&&!player[k].leftkeydown&&!player[k].rightkeydown&&!player[k].crouchkeydown&&player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife&&player[k].weaponmissdelay<=0)player[k].targetanimation=knifeslashstartanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<4.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].crouchkeydown&&player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==sword&&player[k].weaponmissdelay<=0)player[k].targetanimation=swordslashanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<4.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].crouchkeydown&&player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==staff&&player[k].weaponmissdelay<=0&&!player[k].leftkeydown&&!player[k].rightkeydown&&!player[k].forwardkeydown)player[k].targetanimation=staffhitanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<4.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight&&!player[k].crouchkeydown&&player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==staff&&player[k].weaponmissdelay<=0)player[k].targetanimation=staffspinhitanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=spinkickanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height==lowheight&&animation[player[k].targetanimation].attack!=normalattack)player[k].targetanimation=lowkickanim;
+ }
+ else {
+ if(findDistancefast(&player[k].coords,&player[i].coords)<4.5*(player[k].scale*5)*(player[k].scale*5)){
+ if(player[k].weaponactive==-1)randattack=abs(Random()%5);
+ else randattack=abs(Random()%5);
+ if(player[k].weaponactive==-1&&findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)){
+ if(randattack==0&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=sweepanim;
+ else if(randattack==1&&animation[player[i].targetanimation].height!=lowheight&&player[k].weaponactive==-1)player[k].targetanimation=upunchanim;
+ else if(randattack==2&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=spinkickanim;
+ else if(animation[player[i].targetanimation].height==lowheight)player[k].targetanimation=lowkickanim;
+ }
+ if(player[k].weaponactive!=-1){
+ if((tutoriallevel!=1||player[k].weaponactive==-1)&&findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&randattack==0&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=sweepanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)/*&&animation[player[i].targetanimation].height!=lowheight*/&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife&&player[k].weaponmissdelay<=0)player[k].targetanimation=knifeslashstartanim;
+ //else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5&&player[k].weaponactive!=-1&&player[i].staggerdelay>0&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife)player[k].targetanimation=knifefollowanim;
+ else if(!(player[0].victim==&player[i]&&player[0].hasvictim&&player[0].targetanimation==swordslashanim)&&weapons.type[player[k].weaponids[player[k].weaponactive]]==sword&&player[k].weaponmissdelay<=0)player[k].targetanimation=swordslashanim;
+ else if(!(player[0].victim==&player[i]&&player[0].hasvictim&&player[0].targetanimation==swordslashanim)&&weapons.type[player[k].weaponids[player[k].weaponactive]]==staff&&player[k].weaponmissdelay<=0&&randattack<3)player[k].targetanimation=staffhitanim;
+ else if(!(player[0].victim==&player[i]&&player[0].hasvictim&&player[0].targetanimation==swordslashanim)&&weapons.type[player[k].weaponids[player[k].weaponactive]]==staff&&player[k].weaponmissdelay<=0&&randattack>=3)player[k].targetanimation=staffspinhitanim;
+ else if((tutoriallevel!=1||player[k].weaponactive==-1)&&findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&randattack==1&&animation[player[i].targetanimation].height!=lowheight)player[k].targetanimation=spinkickanim;
+ else if(findDistancefast(&player[k].coords,&player[i].coords)<2.5*(player[k].scale*5)*(player[k].scale*5)&&animation[player[i].targetanimation].height==lowheight&&animation[player[k].targetanimation].attack!=normalattack)player[k].targetanimation=lowkickanim;
+ }
+ }
+ }
+ if(player[k].targetanimation==upunchanim&&player[k].creature==wolftype)player[k].targetanimation=wolfslapanim;
+ }
+ if((tutoriallevel!=1||tutorialstage==22)&&player[i].howactive<typedead1&&findDistancefast(&player[k].coords,&player[i].coords)<1.5*(player[k].scale*5)*(player[k].scale*5)&&!player[i].skeleton.free&&player[i].targetanimation!=getupfrombackanim&&player[i].targetanimation!=getupfromfrontanim&&(((player[i].stunned>0&&player[k].madskills)||(player[i].surprised>0)||player[i].aitype==passivetype)||(player[k].weaponactive!=-1&&player[i].stunned>0))&&normaldotproduct(player[i].facing,player[i].coords-player[k].coords)>0&&(k==0)){
+ if(player[k].weaponactive==-1){
+ player[i].targetanimation=sneakattackedanim;
+ player[i].currentanimation=sneakattackedanim;
+ player[k].currentanimation=sneakattackanim;
+ player[k].targetanimation=sneakattackanim;
+ player[k].oldcoords=player[k].coords;
+ player[k].coords=player[i].coords;
+ }
+ if(player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife){
+ player[i].targetanimation=knifesneakattackedanim;
+ player[i].currentanimation=knifesneakattackedanim;
+ player[k].currentanimation=knifesneakattackanim;
+ player[k].targetanimation=knifesneakattackanim;
+ player[i].oldcoords=player[i].coords;
+ player[i].coords=player[k].coords;
+ }
+ if(player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==sword){
+ player[i].targetanimation=swordsneakattackedanim;
+ player[i].currentanimation=swordsneakattackedanim;
+ player[k].currentanimation=swordsneakattackanim;
+ player[k].targetanimation=swordsneakattackanim;
+ player[i].oldcoords=player[i].coords;
+ player[i].coords=player[k].coords;
+ }
+ if(player[k].weaponactive==-1||weapons.type[player[k].weaponids[player[k].weaponactive]]!=staff){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ player[i].targettilt2=0;
+ player[i].targetframe=1;
+ player[i].currentframe=0;
+ player[i].target=0;
+ player[i].velocity=0;
+ player[k].targettilt2=player[i].targettilt2;
+ player[k].currentframe=player[i].currentframe;
+ player[k].targetframe=player[i].targetframe;
+ player[k].target=player[i].target;
+ player[k].velocity=0;
+ player[k].targetrotation=player[i].rotation;
+ player[k].rotation=player[i].rotation;
+ player[i].targetrotation=player[i].rotation;
+ }
+ }
+ if(animation[player[k].targetanimation].attack==normalattack&&player[k].victim==&player[i]&&(!player[i].skeleton.free)){
+ oldattackkey=1;
+ player[k].targetframe=0;
+ player[k].target=0;
+ //player[k].velocity=0;
+
+ rotatetarget=player[i].coords-player[k].coords;
+ Normalise(&rotatetarget);
+ player[k].targetrotation=-asin(0-rotatetarget.x);
+ player[k].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[k].targetrotation=180-player[k].targetrotation;
+
+ player[k].targettilt2=-asin(rotatetarget.y)*360/6.28;//*-70;
+
+ player[k].lastattack3=player[k].lastattack2;
+ player[k].lastattack2=player[k].lastattack;
+ player[k].lastattack=player[k].targetanimation;
+ //player[k].targettilt2=0;
+ //slomo=1;
+ //slomodelay=.2;
+ }
+ if(player[k].targetanimation==knifefollowanim&&player[k].victim==&player[i]){
+ rotatetarget=player[i].coords-player[k].coords;
+ Normalise(&rotatetarget);
+ player[k].targetrotation=-asin(0-rotatetarget.x);
+ player[k].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[k].targetrotation=180-player[k].targetrotation;
+ player[k].targettilt2=-asin(rotatetarget.y)*360/6.28;//*-70;
+ oldattackkey=1;
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ player[i].targetanimation=knifefollowedanim;
+ player[i].currentanimation=knifefollowedanim;
+ player[i].targettilt2=0;
+ player[i].targettilt2=player[k].targettilt2;
+ player[i].targetframe=1;
+ player[i].currentframe=0;
+ player[i].target=0;
+ player[i].velocity=0;
+ player[k].currentanimation=knifefollowanim;
+ player[k].targetanimation=knifefollowanim;
+ player[k].targettilt2=player[i].targettilt2;
+ player[k].currentframe=player[i].currentframe;
+ player[k].targetframe=player[i].targetframe;
+ player[k].target=player[i].target;
+ player[k].velocity=0;
+ player[k].oldcoords=player[k].coords;
+ player[i].coords=player[k].coords;
+ player[i].targetrotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ player[k].rotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ }
+ }
+ }
+ bool hasstaff=0;
+ if(player[k].weaponactive!=-1){
+ if(weapons.type[player[k].weaponids[player[k].weaponactive]]==staff)hasstaff=1;
+ }
+ if(numplayers>1)
+ for(i=0;i<numplayers;i++){
+ if(i==k)i++;
+ if((playerrealattackkeydown||player[i].dead||!hasstaff)&&(k==0||i==0)&&i!=k&&i<numplayers&&k<numplayers&&animation[player[k].targetanimation].attack==neutral&&k==0){
+ if(!player[i].dead||!realthreat||(player[k].weaponactive==-1&&player[k].crouchkeydown))
+ if(player[i].skeleton.free)
+ if(findDistancefast(&player[k].coords,&player[i].coords)<3.5*(player[k].scale*5)*(player[k].scale*5)&&(player[i].dead||player[i].skeleton.longdead>1000||player[k].isRun()||(hasstaff)||(player[k].weaponactive!=-1&&player[i].skeleton.free&&(player[i].skeleton.longdead>2000||player[i].damage>player[i].damagetolerance/8||player[i].bloodloss>player[i].damagetolerance/2)&&findDistancefast(&player[k].coords,&player[i].coords)<1.5*(player[k].scale*5)*(player[k].scale*5)))){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ if(player[k].weaponactive!=-1&&tutoriallevel!=1){
+ if(player[k].crouchkeydown&&player[k].weaponactive!=-1&&weapons.type[player[k].weaponids[player[k].weaponactive]]==knife&&findDistancefast(&player[k].coords,&player[i].coords)<1.5*(player[k].scale*5)*(player[k].scale*5))player[k].targetanimation=crouchstabanim;
+ if(player[k].crouchkeydown&&findDistancefast(&player[k].coords,&player[i].coords)<1.5*(player[k].scale*5)*(player[k].scale*5)/*&&player[i].dead!=2*/&&weapons.type[player[k].weaponids[player[k].weaponactive]]==sword)player[k].targetanimation=swordgroundstabanim;
+ if(/*(player[k].crouchkeydown||!player[i].dead)&&*/findDistancefast(&player[k].coords,&player[i].coords)<3.5*(player[k].scale*5)*(player[k].scale*5)/*&&player[i].dead!=2*/&&weapons.type[player[k].weaponids[player[k].weaponactive]]==staff)player[k].targetanimation=staffgroundsmashanim;
+ }
+ if(findDistancefast(&player[k].coords,&player[i].coords)<2.5&&player[k].crouchkeydown&&player[k].targetanimation!=crouchstabanim&&(player[k].weaponactive==-1)&&player[i].dead&&player[i].skeleton.free&&player[i].skeleton.longdead>1000){
+ player[k].targetanimation=killanim;
+ for(j=0;j<terrain.numdecals;j++){
+ if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&terrain.decalalivetime[j]<2){
+ terrain.DeleteDecal(j);
+ }
+ }
+ for(l=0;l<objects.numobjects;l++){
+ if(objects.model[l].type==decalstype)
+ for(j=0;j<objects.model[l].numdecals;j++){
+ if((objects.model[l].decaltype[j]==blooddecal||objects.model[l].decaltype[j]==blooddecalslow)&&objects.model[l].decalalivetime[j]<2){
+ objects.model[l].DeleteDecal(j);
+ }
+ }
+ }
+ }
+ if(!player[i].dead||musictype!=2)
+ if(findDistancefast(&player[k].coords,&player[i].coords)<3.5&&(player[k].isRun()||(player[k].isIdle()&&player[k].attackkeydown))&&(player[k].staggerdelay<=0&&(player[i].dead||(player[i].skeleton.longdead<300&&player[k].lastattack!=spinkickanim&&player[i].skeleton.free)))&&(!player[i].dead||musictype!=stream_music2)){
+ player[k].targetanimation=dropkickanim;
+ for(j=0;j<terrain.numdecals;j++){
+ if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&terrain.decalalivetime[j]<2){
+ terrain.DeleteDecal(j);
+ }
+ }
+ for(l=0;l<objects.numobjects;l++){
+ if(objects.model[l].type==decalstype)
+ for(j=0;j<objects.model[l].numdecals;j++){
+ if((objects.model[l].decaltype[j]==blooddecal||objects.model[l].decaltype[j]==blooddecalslow)&&objects.model[l].decalalivetime[j]<2){
+ objects.model[l].DeleteDecal(j);
+ }
+ }
+ }
+ }
+ }
+ if(animation[player[k].targetanimation].attack==normalattack&&player[k].victim==&player[i]&&(!player[i].skeleton.free||player[k].targetanimation==killanim||player[k].targetanimation==crouchstabanim||player[k].targetanimation==swordgroundstabanim||player[k].targetanimation==staffgroundsmashanim||player[k].targetanimation==dropkickanim)){
+ oldattackkey=1;
+ player[k].targetframe=0;
+ player[k].target=0;
+ //player[k].velocity=0;
+
+ rotatetarget=player[i].coords-player[k].coords;
+ if(player[k].targetanimation==crouchstabanim||player[k].targetanimation==swordgroundstabanim||player[k].targetanimation==staffgroundsmashanim){
+ rotatetarget=(player[i].coords+(player[i].skeleton.joints[player[i].skeleton.jointlabels[abdomen]].position+player[i].skeleton.joints[player[i].skeleton.jointlabels[neck]].position)/2*player[i].scale)-player[k].coords;
+ }
+ Normalise(&rotatetarget);
+ player[k].targetrotation=-asin(0-rotatetarget.x);
+ player[k].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[k].targetrotation=180-player[k].targetrotation;
+
+ if(player[k].targetanimation==crouchstabanim||player[k].targetanimation==swordgroundstabanim){
+ player[k].targetrotation+=(float)(abs(Random()%100)-50)/4;
+ }
+
+ player[k].targettilt2=-asin(rotatetarget.y)*360/6.28;//*-70;
+ if(player[k].targetanimation==staffgroundsmashanim)player[k].targettilt2+=10;
+
+ player[k].lastattack3=player[k].lastattack2;
+ player[k].lastattack2=player[k].lastattack;
+ player[k].lastattack=player[k].targetanimation;
+
+ if(player[k].targetanimation==swordgroundstabanim){
+ player[k].targetrotation+=30;
+ }
+ //player[k].targettilt2=0;
+ //slomo=1;
+ //slomodelay=.2;
+ }
+ }
+ }
+ if(!player[k].hasvictim){
+ for(i=0;i<numplayers;i++){
+ if((player[k].hasvictim==0)&&i!=k&&(i==0||k==0)&&!player[i].skeleton.free){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ }
+ if(player[k].hasvictim&&!player[i].skeleton.free)
+ if(findDistancefast(&player[k].coords,&player[i].coords)<findDistancefast(&player[k].coords,&player[k].victim->coords)&&i!=k&&(i==0||k==0)){
+ player[k].victim=&player[i];
+ }
+ }
+ }
+ if(player[k].aitype==playercontrolled)
+ if(player[k].attackkeydown&&(player[k].isRun())&&player[k].wasRun()&&((player[k].hasvictim&&findDistancefast(&player[k].coords,&player[k].victim->coords)<12*(player[k].scale*5)*(player[k].scale*5)&&findDistancefast(&player[k].coords,&player[k].victim->coords)>7*(player[k].scale*5)*(player[k].scale*5)&&!player[k].victim->skeleton.free&&player[k].victim->targetanimation!=getupfrombackanim&&player[k].victim->targetanimation!=getupfromfrontanim&&animation[player[k].victim->targetanimation].height!=lowheight&&player[k].aitype!=playercontrolled&&normaldotproduct(player[k].facing,player[k].victim->coords-player[k].coords)>0&&player[k].rabbitkickenabled)||player[k].jumpkeydown)){
+ oldattackkey=1;
+ player[k].targetanimation=rabbitkickanim;
+ player[k].targetframe=0;
+ player[k].target=0;
+ }
+ if(animation[player[k].targetanimation].attack&&k==0){
+ numattacks++;
+ bool armedstaff=0;
+ if(player[k].weaponactive!=-1){
+ if(weapons.type[player[k].weaponids[player[k].weaponactive]]==staff)armedstaff=1;
+ }
+ bool armedsword=0;
+ if(player[k].weaponactive!=-1){
+ if(weapons.type[player[k].weaponids[player[k].weaponactive]]==sword)armedsword=1;
+ }
+ bool armedknife=0;
+ if(player[k].weaponactive!=-1){
+ if(weapons.type[player[k].weaponids[player[k].weaponactive]]==knife)armedknife=1;
+ }
+ if(armedstaff)numstaffattack++;
+ else if(armedsword)numswordattack++;
+ else if(armedknife)numknifeattack++;
+ else numunarmedattack++;
+ }
+ }
+ }
+ }
+
+ //Collisions
+ static float collisionradius;
+ if(numplayers>1)
+ for(k=0;k<numplayers;k++){
+ for(i=k;i<numplayers;i++){
+ if(i==k)i++;
+ if(i<numplayers)
+ if((animation[player[i].targetanimation].attack!=reversed&&animation[player[i].targetanimation].attack!=reversal&&animation[player[k].targetanimation].attack!=reversed&&animation[player[k].targetanimation].attack!=reversal)||(i!=0&&k!=0))
+ if((animation[player[i].currentanimation].attack!=reversed&&animation[player[i].currentanimation].attack!=reversal&&animation[player[k].currentanimation].attack!=reversed&&animation[player[k].currentanimation].attack!=reversal)||(i!=0&&k!=0))
+ if(player[i].howactive<=typesleeping&&player[k].howactive<=typesleeping)
+ if(player[i].howactive!=typesittingwall&&player[k].howactive!=typesittingwall)
+ if(i!=k&&player[i].whichpatchx==player[k].whichpatchx&&player[i].whichpatchz==player[k].whichpatchz&&player[k].skeleton.oldfree==player[k].skeleton.free&&player[i].skeleton.oldfree==player[i].skeleton.free&&player[i].targetanimation!=climbanim&&player[i].targetanimation!=hanganim&&player[k].targetanimation!=climbanim&&player[k].targetanimation!=hanganim)
+ if(player[i].coords.y>player[k].coords.y-3)
+ if(player[i].coords.y<player[k].coords.y+3)
+ if(player[i].coords.x>player[k].coords.x-3)
+ if(player[i].coords.x<player[k].coords.x+3)
+ if(player[i].coords.z>player[k].coords.z-3)
+ if(player[i].coords.z<player[k].coords.z+3){
+ if(findDistancefast(&player[i].coords,&player[k].coords)<3*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ if(player[i].onfire||player[k].onfire){
+ if(!player[i].onfire)player[i].CatchFire();
+ if(!player[k].onfire)player[k].CatchFire();
+ }
+ }
+
+ tempcoords1=player[i].coords;
+ tempcoords2=player[k].coords;
+ if(!player[i].skeleton.oldfree)tempcoords1.y+=player[i].skeleton.joints[player[i].skeleton.jointlabels[abdomen]].position.y*player[i].scale;
+ if(!player[k].skeleton.oldfree)tempcoords2.y+=player[k].skeleton.joints[player[k].skeleton.jointlabels[abdomen]].position.y*player[k].scale;
+ collisionradius=1.2*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5);
+ if(player[0].hasvictim)
+ if(player[0].targetanimation==rabbitkickanim&&(k==0||i==0)&&!player[0].victim->skeleton.free)collisionradius=3;
+ if((!player[i].skeleton.oldfree||!player[k].skeleton.oldfree)&&(findDistancefast(&tempcoords1,&tempcoords2)<collisionradius||findDistancefast(&player[i].coords,&player[k].coords)<collisionradius)){
+ if(k==0)
+ if(player[k].targetanimation==jumpdownanim&&!player[k].skeleton.oldfree&&!player[k].skeleton.free&&player[i].skeleton.oldfree&&player[i].skeleton.free&&player[i].dead&&player[k].lastcollide<=0&&abs(player[i].coords.y-player[k].coords.y)<.2&&findDistancefast(&player[k].coords,&player[i].coords)<.7*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ player[k].coords.y=player[i].coords.y;
+ player[i].velocity=player[k].velocity;
+ player[i].skeleton.free=0;
+ player[i].rotation=0;
+ player[i].RagDoll(0);
+ player[i].DoDamage(20);
+ if(k==0)camerashake+=.3;
+ player[i].skeleton.longdead=0;
+ player[k].lastcollide=1;
+ }
+ if(i==0)
+ if(player[i].targetanimation==jumpdownanim&&!player[i].skeleton.oldfree&&!player[i].skeleton.free&&player[k].skeleton.oldfree&&player[k].skeleton.free&&player[k].dead&&player[i].lastcollide<=0&&abs(player[i].coords.y-player[k].coords.y)<.2&&findDistancefast(&player[k].coords,&player[i].coords)<.7*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ player[i].coords.y=player[k].coords.y;
+ player[k].velocity=player[i].velocity;
+ player[k].skeleton.free=0;
+ player[k].rotation=0;
+ player[k].RagDoll(0);
+ player[k].DoDamage(20);
+ if(i==0)camerashake+=.3;
+ player[k].skeleton.longdead=0;
+ player[i].lastcollide=1;
+ }
+
+ if((player[i].skeleton.oldfree==1&&findLengthfast(&player[i].velocity)>1)||(player[k].skeleton.oldfree==1&&findLengthfast(&player[k].velocity)>1)||(player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0)){
+ rotatetarget=player[k].velocity-player[i].velocity;
+ if(((player[i].targetanimation!=getupfrombackanim&&player[i].targetanimation!=getupfromfrontanim)||player[i].skeleton.free)&&((player[k].targetanimation!=getupfrombackanim&&player[k].targetanimation!=getupfromfrontanim)||player[k].skeleton.free))
+ if(((((findLengthfast(&rotatetarget)>150&&(i!=0&&k!=0))||(findLengthfast(&rotatetarget)>50&&player[0].rabbitkickragdoll/*currentanimation==rabbitkickanim*/&&(i==0||k==0)))&&normaldotproduct(rotatetarget,player[k].coords-player[i].coords)>0)&&((i==0||k==0)||((player[i].skeleton.oldfree==1&&k!=0&&animation[player[k].currentanimation].attack==neutral)||(player[k].skeleton.oldfree==1&&i!=0&&animation[player[i].currentanimation].attack==neutral)||(player[i].isFlip()&&!player[i].skeleton.oldfree&&(i==0||k==0))||(player[k].isFlip()&&!player[k].skeleton.oldfree&&(i==0||k==0))||(i==0||k==0))))||((player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip())&&(player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim||player[k].isFlip())&&(i==0||k==0)&&(!player[i].skeleton.oldfree&&!player[k].skeleton.oldfree))){
+ //If hit by body
+ if((i!=0||player[i].skeleton.free)&&(k!=0||player[k].skeleton.free)||(animation[player[i].targetanimation].height==highheight&&animation[player[k].targetanimation].height==highheight)){
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=player[i].coords.x;
+ gLoc[1]=player[i].coords.y;
+ gLoc[2]=player[i].coords.z;
+ vel[0]=player[i].velocity.x;
+ vel[1]=player[i].velocity.y;
+ vel[2]=player[i].velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 256);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ //player[i].velocity=player[k].velocity;
+ //player[k].velocity=player[i].velocity;
+
+ player[i].RagDoll(0);
+ if(player[i].damage>player[i].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[i].dead){
+ bonus=aimbonus;
+ bonustime=0;
+ bonusvalue=150;
+ }
+ player[i].DoDamage(findLengthfast(&rotatetarget)/4);
+ player[k].RagDoll(0);
+ if(player[k].damage>player[k].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[k].dead){
+ bonus=aimbonus;
+ bonustime=0;
+ bonusvalue=150;
+ }
+ player[k].DoDamage(findLengthfast(&rotatetarget)/4);
+
+ //if(player[i].skeleton.oldfree){
+ for(j=0;j<player[i].skeleton.num_joints;j++){
+ player[i].skeleton.joints[j].velocity=player[i].skeleton.joints[j].velocity/5+player[k].velocity;
+ }
+ //}
+ //if(player[k].skeleton.oldfree){
+ for(j=0;j<player[k].skeleton.num_joints;j++){
+ player[k].skeleton.joints[j].velocity=player[k].skeleton.joints[j].velocity/5+player[i].velocity;
+ }
+ //}
+
+ }
+ }
+ if((animation[player[i].targetanimation].attack==neutral||animation[player[i].targetanimation].attack==normalattack)&&(animation[player[k].targetanimation].attack==neutral||animation[player[k].targetanimation].attack==normalattack)){
+ //If bumped
+ if(player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0){
+ if(findDistancefast(&player[k].coords,&player[i].coords)<.5*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ rotatetarget=player[k].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[k].coords=(player[k].coords+player[i].coords)/2;
+ player[i].coords=player[k].coords-rotatetarget*fast_sqrt(.6)/2*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5);
+ player[k].coords+=rotatetarget*fast_sqrt(.6)/2*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5);
+ if(player[k].howactive==typeactive||hostile)
+ if(player[k].isIdle()){
+ if(player[k].howactive<typesleeping){
+ player[k].targetanimation=player[k].getStop();
+ player[k].targetframe=0;
+ player[k].target=0;
+ }
+ else if(player[k].howactive==typesleeping)
+ {
+ player[k].targetanimation=getupfromfrontanim;
+ player[k].targetframe=0;
+ player[k].target=0;
+ }
+ if(!editorenabled)player[k].howactive=typeactive;
+ }
+ if(player[i].howactive==typeactive||hostile)
+ if(player[i].isIdle()){
+ if(player[i].howactive<typesleeping){
+ player[i].targetanimation=player[i].getStop();
+ player[i].targetframe=0;
+ player[i].target=0;
+ }
+ else
+ {
+ player[i].targetanimation=getupfromfrontanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ }
+ if(!editorenabled)player[i].howactive=typeactive;
+ }
+ }
+ if(hostile){
+ if(k==0&&i!=0&&player[k].targetanimation==jumpdownanim&&!player[i].isCrouch()&&player[i].targetanimation!=rollanim&&!player[k].skeleton.oldfree&&!player[k].skeleton.free&&player[k].lastcollide<=0&&player[k].velocity.y<-10){
+ player[i].velocity=player[k].velocity;
+ player[k].velocity=player[k].velocity*-.5;
+ //player[i].velocity.y-=10;
+ player[k].velocity.y=player[i].velocity.y;
+ player[i].DoDamage(20);
+ player[i].RagDoll(0);
+ player[k].lastcollide=1;
+ if(k==0){
+ bonus=AboveBonus;
+ bonustime=0;
+ bonusvalue=50;
+ }
+ }
+ if(i==0&&k!=0&&player[i].targetanimation==jumpdownanim&&!player[k].isCrouch()&&player[k].targetanimation!=rollanim&&!player[i].skeleton.oldfree&&!player[i].skeleton.free&&player[i].lastcollide<=0&&player[i].velocity.y<-10){
+ player[k].velocity=player[i].velocity;
+ player[i].velocity=player[i].velocity*-.3;
+ //player[k].velocity.y-=10;
+ player[i].velocity.y=player[k].velocity.y;
+ player[k].DoDamage(20);
+ player[k].RagDoll(0);
+ player[i].lastcollide=1;
+ if(i==0){
+ bonus=AboveBonus;
+ bonustime=0;
+ bonusvalue=50;
+ }
+ }
+ }
+ }
+ }
+ }
+ player[i].CheckKick();
+ player[k].CheckKick();
+ }
+ }
+ }
+ }
+
+ for(k=0;k<numplayers;k++){
+ for(i=k;i<numplayers;i++){
+ if(i==k)i++;
+ if(i<numplayers&&i!=k&&player[k].skeleton.free==0&&player[i].skeleton.oldfree==0&&(player[i].targetanimation==jumpupanim||player[k].targetanimation==jumpupanim)&&(player[i].aitype==playercontrolled||player[k].aitype==playercontrolled)&&((player[i].aitype==attacktypecutoff&&player[i].stunned<=0)||(player[k].aitype==attacktypecutoff&&player[k].stunned<=0))){
+ if(findDistancefast(&player[i].coords,&player[k].coords)<10*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)&&findDistancefastflat(&player[i].coords,&player[k].coords)<2*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ if(player[i].targetanimation==jumpupanim&&player[k].targetanimation!=getupfrombackanim&&player[k].targetanimation!=getupfromfrontanim&&animation[player[k].targetanimation].height==middleheight&&normaldotproduct(player[i].velocity,player[k].coords-player[i].coords)<0&&((player[k].aitype==playercontrolled&&player[k].attackkeydown)||player[k].aitype!=playercontrolled)){
+ player[i].victim=&player[k];
+ player[i].targetanimation=jumpreversedanim;
+ player[i].currentanimation=jumpreversedanim;
+ player[k].currentanimation=jumpreversalanim;
+ player[k].targetanimation=jumpreversalanim;
+ player[i].targettilt2=0;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ player[k].currentframe=0;
+ player[k].targetframe=1;
+ if(player[i].coords.y<player[k].coords.y+1){
+ player[i].targetanimation=rabbitkickreversedanim;
+ player[i].currentanimation=rabbitkickreversedanim;
+ player[k].currentanimation=rabbitkickreversalanim;
+ player[k].targetanimation=rabbitkickreversalanim;
+ player[k].currentframe=1;
+ player[k].targetframe=2;
+ player[i].currentframe=1;
+ player[i].targetframe=2;
+ }
+ player[k].targettilt2=0;
+ player[i].target=0;
+ player[i].velocity=0;
+ player[k].velocity=0;
+ player[k].oldcoords=player[k].coords;
+ player[i].coords=player[k].coords;
+ player[k].targetrotation=player[i].targetrotation;
+ player[k].rotation=player[i].targetrotation;
+ player[k].victim=&player[i];
+ if(player[k].aitype==attacktypecutoff)player[k].stunned=.5;
+ }
+ if(player[k].targetanimation==jumpupanim&&player[i].targetanimation!=getupfrombackanim&&player[i].targetanimation!=getupfromfrontanim&&animation[player[i].targetanimation].height==middleheight&&normaldotproduct(player[k].velocity,player[i].coords-player[k].coords)<0&&((player[i].aitype==playercontrolled&&player[i].attackkeydown)||player[i].aitype!=playercontrolled)){
+ player[k].victim=&player[i];
+ player[k].targetanimation=jumpreversedanim;
+ player[k].currentanimation=jumpreversedanim;
+ player[i].currentanimation=jumpreversalanim;
+ player[i].targetanimation=jumpreversalanim;
+ player[k].targettilt2=0;
+ player[i].targettilt2=0;
+ player[k].currentframe=0;
+ player[k].targetframe=1;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ if(player[k].coords.y<player[i].coords.y+1){
+ player[k].targetanimation=rabbitkickreversedanim;
+ player[k].currentanimation=rabbitkickreversedanim;
+ player[i].currentanimation=rabbitkickreversalanim;
+ player[i].targetanimation=rabbitkickreversalanim;
+ player[k].currentframe=1;
+ player[k].targetframe=2;
+ player[i].currentframe=1;
+ player[i].targetframe=2;
+ }
+ player[k].target=0;
+ player[k].velocity=0;
+ player[i].velocity=0;
+ player[i].oldcoords=player[i].coords;
+ player[k].coords=player[i].coords;
+ player[i].targetrotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ player[i].victim=&player[k];
+ if(player[i].aitype==attacktypecutoff)player[i].stunned=.5;
+ }
+ }
+ }
+ }
+ }
+
+ for(k=0;k<numplayers;k++)
+ if(player[k].immobile&&k!=0)player[k].coords=player[k].realoldcoords;
+
+
+ //pile
+ /*
+ XYZ tempdiff;
+ XYZ tempoldpos;
+ XYZ temp1,temp2;
+ bool isgood;
+ static float checkdelay;
+ checkdelay-=multiplier;
+ int m;
+ static bool checkedcoll[maxplayers][maxplayers];
+ static bool above[maxplayers];
+
+ for(i=0;i<maxplayers;i++){
+ for(j=0;j<maxplayers;j++){
+ checkedcoll[i][j]=0;
+ }
+ }
+
+ if(numplayers>1&&checkdelay<=0){
+ checkdelay=.015;
+ for(k=0;k<numplayers;k++){
+ if(player[k].skeleton.free!=2)above[k]=-1;
+
+ for(i=k;i<numplayers;i++){
+ if(i==k)i++;
+ if(i<numplayers)
+ if(!checkedcoll[i][k]){
+ checkedcoll[i][k]=1;
+ checkedcoll[k][i]=1;
+ if(player[i].skeleton.free&&player[k].skeleton.free)
+ if(player[i].skeleton.free!=2||player[k].skeleton.free!=2)
+ if(i!=k&&player[i].whichpatchx==player[k].whichpatchx&&player[i].whichpatchz==player[k].whichpatchz)
+ if(player[i].coords.y>player[k].coords.y-3)
+ if(player[i].coords.y<player[k].coords.y+3)
+ if(player[i].coords.x>player[k].coords.x-3)
+ if(player[i].coords.x<player[k].coords.x+3)
+ if(player[i].coords.z>player[k].coords.z-3)
+ if(player[i].coords.z<player[k].coords.z+3)
+ if(findDistancefast(&player[i].coords,&player[k].coords)<3*((player[i].scale+player[k].scale)*2.5)*((player[i].scale+player[k].scale)*2.5)){
+ int stuck,moving;
+ if((player[i].skeleton.longdead>player[k].skeleton.longdead&&player[k].skeleton.free!=2)||player[i].skeleton.free==2){
+ stuck=i;
+ moving=k;
+ }
+ else
+ {
+ moving=i;
+ stuck=k;
+ }
+ isgood=1;
+
+ if(isgood){
+ above[moving]=stuck;
+ for(l=0;l<player[moving].skeleton.num_joints;l++){
+ for(m=0;m<player[stuck].skeleton.num_joints;m++){
+ while(findDistancefast(player[moving].skeleton.joints[l].position+player[moving].coords,player[stuck].skeleton.joints[m].position+player[stuck].coords)<.25)
+ {
+ player[moving].skeleton.joints[l].position.y+=.003;
+ if(player[moving].skeleton.joints[l].velocity.y<-.05)player[moving].skeleton.joints[l].velocity.y+=.003/.015/2;
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ */
+
+ if(!IsKeyDown(theKeyMap, MAC_N_KEY)){
+ texturesizetogglekeydown=0;
+ }
+
+ for(k=0;k<numplayers;k++){
+ if(!isnormal(player[k].coords.x)||!isnormal(player[k].coords.y)||!isnormal(player[k].coords.z)){
+ if(!isnormal(player[k].coords.x)||!isnormal(player[k].coords.y)||!isnormal(player[k].coords.z)){
+ player[k].DoDamage(1000);
+ }
+ }
+ }
+
+ static bool respawnkeydown;
+ if(!editorenabled&&(whichlevel!=-2&&(IsKeyDown(theKeyMap, MAC_Z_KEY)&&IsKeyDown(theKeyMap, MAC_COMMAND_KEY)&&debugmode&&!editorenabled)||(IsKeyDown(theKeyMap, jumpkey)&&!respawnkeydown&&!oldattackkey&&player[0].dead))){
+ targetlevel=whichlevel;
+ loading=1;
+ leveltime=5;
+ }
+ if(!IsKeyDown(theKeyMap, jumpkey))respawnkeydown=0;
+ if(IsKeyDown(theKeyMap, jumpkey))respawnkeydown=1;
+
+
+
+
+ if(whichlevel!=-2&&IsKeyDown(theKeyMap, MAC_K_KEY)&&IsKeyDown(theKeyMap, MAC_SHIFT_KEY)&&!slomotogglekeydown&&debugmode&&!editorenabled){
+ targetlevel++;
+ if(targetlevel>numchallengelevels-1)targetlevel=0;
+ loading=1;
+ leveltime=5;
+ slomotogglekeydown=1;
+ }
+
+ /*
+ if(IsKeyDown(theKeyMap, MAC_Z_KEY)){
+ //Respawn
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ changedelay=0;
+ for(k=0;k<numplayers;k++){
+ player[k].dead=0;
+ player[k].damage=0;
+ player[k].permanentdamage=0;
+ if(player[k].skeleton.free==2)player[k].skeleton.free=1;
+ player[k].aitype=passivetype;
+ }
+ player[0].aitype=playercontrolled;
+ }
+ */
+
+ static bool movekey;
+ static bool connected;
+ /*player[0].forwardkeydown=IsKeyDown(theKeyMap, MAC_W_KEY);
+ player[0].leftkeydown=IsKeyDown(theKeyMap, MAC_A_KEY);
+ player[0].backkeydown=IsKeyDown(theKeyMap, MAC_S_KEY);
+ player[0].rightkeydown=IsKeyDown(theKeyMap, MAC_D_KEY);
+ player[0].jumpkeydown=IsKeyDown(theKeyMap, MAC_SPACE_KEY);
+ player[0].crouchkeydown=IsKeyDown(theKeyMap, MAC_SHIFT_KEY);*/
+
+ //if(!player[0].crouchkeydown)player[0].crouchkeydown=IsKeyDown(theKeyMap, MAC_CONTROL_KEY);
+
+ for(int i=0;i<numplayers;i++){
+ if(!player[i].skeleton.free){
+ oldtargetrotation=player[i].targetrotation;
+ if(i==0&&indialogue==-1){
+ if(!animation[player[0].targetanimation].attack&&player[0].targetanimation!=staggerbackhighanim&&player[0].targetanimation!=staggerbackhardanim&&player[0].targetanimation!=crouchremoveknifeanim&&player[0].targetanimation!=removeknifeanim&&player[0].targetanimation!=backhandspringanim&&player[0].targetanimation!=dodgebackanim&&player[0].targetanimation!=walljumprightkickanim&&player[0].targetanimation!=walljumpleftkickanim){
+ if(!cameramode)player[0].targetrotation=-rotation+180;
+ if(cameramode)player[0].targetrotation=0;
+ }
+
+ facing=0;
+ facing.z=-1;
+
+ flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
+ if(cameramode){facing=flatfacing;}
+ else{
+ facing=DoRotation(facing,-rotation2,0,0);
+ facing=DoRotation(facing,0,0-rotation,0);
+ }
+
+ player[0].lookrotation=-rotation;
+
+ player[i].targetheadrotation=rotation;
+ player[i].targetheadrotation2=rotation2;
+ }
+ if(i!=0&&player[i].aitype==playercontrolled&&indialogue==-1){
+ if(!animation[player[i].targetanimation].attack&&player[i].targetanimation!=staggerbackhighanim&&player[i].targetanimation!=staggerbackhardanim&&player[i].targetanimation!=crouchremoveknifeanim&&player[i].targetanimation!=removeknifeanim&&player[i].targetanimation!=backhandspringanim&&player[i].targetanimation!=dodgebackanim&&player[i].targetanimation!=walljumprightkickanim&&player[i].targetanimation!=walljumpleftkickanim){
+ player[i].targetrotation=-player[i].lookrotation+180;
+ }
+
+ facing=0;
+ facing.z=-1;
+
+ flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
+
+ facing=DoRotation(facing,-player[i].lookrotation2,0,0);
+ facing=DoRotation(facing,0,0-player[i].lookrotation,0);
+
+ player[i].targetheadrotation=player[i].lookrotation;
+ player[i].targetheadrotation2=player[i].lookrotation2;
+ }
+ if(indialogue!=-1){
+ rotatetarget=participantfacing[whichdialogue][indialogue][i];
+ Normalise(&rotatetarget);
+ player[i].targetheadrotation=-asin(0-rotatetarget.x);
+ player[i].targetheadrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetheadrotation=180-player[i].targetheadrotation;
+
+ player[i].targetheadrotation*=-1;
+ player[i].targetheadrotation+=180;
+ player[i].targetheadrotation2=-asin(rotatetarget.y)*360/6.28;
+ }
+
+ bool pause;
+
+ if(leveltime<.5)
+ numenvsounds=0;
+
+ player[i].avoidsomething=0;
+
+ for(j=0;j<objects.numobjects;j++){
+ if(objects.onfire[j]){
+ if(findDistancefast(&objects.position[j],&player[i].coords)<objects.scale[j]*objects.scale[j]*200)
+ {
+ if(findDistancefast(&player[i].coords,&objects.position[j])<findDistancefast(&player[i].coords,&player[0].coords)){
+ player[i].collided=0;
+ player[i].avoidcollided=1;
+ if(player[i].avoidsomething==0||findDistancefast(&objects.position[j],&player[i].coords)<findDistancefast(&player[i].coords,&player[i].avoidwhere))
+ player[i].avoidwhere=objects.position[j];
+ }
+ }
+ }
+ }
+
+ //Add avoidwhere to players
+
+ for(j=0;j<numplayers;j++){
+ if(player[j].onfire){
+ if(findDistancefast(&player[j].coords,&player[i].coords)<0.3*0.3*200)
+ {
+ if(findDistancefast(&player[i].coords,&player[j].coords)<findDistancefast(&player[i].coords,&player[0].coords)){
+ player[i].collided=0;
+ player[i].avoidcollided=1;
+ if(player[i].avoidsomething==0||findDistancefast(&player[j].coords,&player[i].coords)<findDistancefast(&player[i].coords,&player[i].avoidwhere))
+ player[i].avoidwhere=objects.position[j];
+ }
+ }
+ }
+ }
+
+ if(player[i].collided>.8)player[i].avoidcollided=0;
+ if(player[i].aitype!=playercontrolled&&indialogue==-1){
+ player[i].jumpclimb=0;
+ //AI
+ if(editorenabled)player[i].stunned=1;
+
+ player[i].pause=0;
+ //if(findDistancefastflat(&player[i].coords,&player[0].coords)<3/*&&player[0].coords.y>player[i].coords.y+.1*/)player[i].pause=1;
+ if(findDistancefastflat(&player[0].coords,&player[i].coords)<30&&player[0].coords.y>player[i].coords.y+2&&!player[0].onterrain)player[i].pause=1;
+
+ /*if(player[i].aitype==passivetype&&player[i].numwaypoints<=1){
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].throwkeydown=0;
+ }*/
+
+ if(player[i].aitype==pathfindtype){
+ if(player[i].finalpathfindpoint==-1){
+ float closestdistance;
+ float tempdist;
+ int closest;
+ XYZ colpoint;
+ closest=-1;
+ closestdistance=-1;
+ for(j=0;j<numpathpoints;j++){
+ if(closest==-1||findDistancefast(&player[i].finalfinaltarget,&pathpoint[j])<closestdistance){
+ closestdistance=findDistancefast(&player[i].finalfinaltarget,&pathpoint[j]);
+ closest=j;
+ player[i].finaltarget=pathpoint[j];
+ }
+ }
+ player[i].finalpathfindpoint=closest;
+ for(j=0;j<numpathpoints;j++){
+ if(numpathpointconnect[j])
+ for(k=0;k<numpathpointconnect[j];k++){
+ DistancePointLine(&player[i].finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
+ if(tempdist*tempdist<closestdistance){
+ if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
+ closestdistance=tempdist*tempdist;
+ closest=j;
+ player[i].finaltarget=colpoint;
+ }
+ }
+ }
+ }
+ player[i].finalpathfindpoint=closest;
+
+ }
+ if(player[i].targetpathfindpoint==-1){
+ float closestdistance;
+ float tempdist;
+ int closest;
+ XYZ colpoint;
+ closest=-1;
+ closestdistance=-1;
+ if(player[i].lastpathfindpoint==-1){
+ for(j=0;j<numpathpoints;j++){
+ if(j!=player[i].lastpathfindpoint)
+ if(closest==-1||(findDistancefast(&player[i].coords,&pathpoint[j])<closestdistance/*&&findDistancefast(&player[i].finaltarget,&pathpoint[j])<findDistancefast(&player[i].finaltarget,&player[i].coords)*/)){
+ closestdistance=findDistancefast(&player[i].coords,&pathpoint[j]);
+ closest=j;
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ for(j=0;j<numpathpoints;j++){
+ if(j!=player[i].lastpathfindpoint)
+ if(numpathpointconnect[j])
+ for(k=0;k<numpathpointconnect[j];k++){
+ DistancePointLine(&player[i].coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
+ if(tempdist*tempdist<closestdistance){
+ if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
+ //if(findDistancefast(&player[i].finaltarget,&colpoint)<findDistancefast(&player[i].finaltarget,&player[i].coords)){
+ closestdistance=tempdist*tempdist;
+ closest=j;
+ //}
+ }
+ }
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ }
+ else
+ {
+ for(j=0;j<numpathpoints;j++){
+ if(j!=player[i].lastpathfindpoint&&j!=player[i].lastpathfindpoint2&&j!=player[i].lastpathfindpoint3&&j!=player[i].lastpathfindpoint4)
+ {
+ connected=0;
+ if(numpathpointconnect[j])
+ for(k=0;k<numpathpointconnect[j];k++){
+ if(pathpointconnect[j][k]==player[i].lastpathfindpoint)connected=1;
+ }
+ if(!connected)
+ if(numpathpointconnect[player[i].lastpathfindpoint])
+ for(k=0;k<numpathpointconnect[player[i].lastpathfindpoint];k++){
+ if(pathpointconnect[player[i].lastpathfindpoint][k]==j)connected=1;
+ }
+ if(connected){
+ tempdist=findPathDist(j,player[i].finalpathfindpoint);
+ if(closest==-1||tempdist<closestdistance){
+ closestdistance=tempdist;
+ closest=j;
+ }
+ }
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ }
+ }
+ player[i].losupdatedelay-=multiplier;
+
+ rotatetarget=pathpoint[player[i].targetpathfindpoint]-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ //player[i].aiupdatedelay=.05;
+
+ if(findDistancefastflat(&player[i].coords,&pathpoint[player[i].targetpathfindpoint])<.6){
+ player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
+ player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
+ player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
+ player[i].lastpathfindpoint=player[i].targetpathfindpoint;
+ if(player[i].lastpathfindpoint2==-1)player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
+ if(player[i].lastpathfindpoint3==-1)player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
+ if(player[i].lastpathfindpoint4==-1)player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
+ player[i].targetpathfindpoint=-1;
+ }
+ if(findDistancefastflat(&player[i].coords,&player[i].finalfinaltarget)<findDistancefastflat(&player[i].coords,&player[i].finaltarget)||findDistancefastflat(&player[i].coords,&player[i].finaltarget)<.6*(player[i].scale*5)*(player[i].scale*5)||player[i].lastpathfindpoint==player[i].finalpathfindpoint){
+ player[i].aitype=passivetype;
+ }
+
+ player[i].forwardkeydown=1;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))player[i].jumpkeydown=1;
+
+ if((tutoriallevel!=1||cananger)&&hostile&&!player[0].dead&&findDistancefast(&player[i].coords,&player[0].coords)<400&&player[i].occluded<25){
+ if(findDistancefast(&player[i].coords,&player[0].coords)<12&&animation[player[0].targetanimation].height!=lowheight&&!editorenabled&&(player[0].coords.y<player[i].coords.y+5||player[0].onterrain))
+ player[i].aitype=attacktypecutoff;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<30&&animation[player[0].targetanimation].height==highheight&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+
+ if(player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
+ player[i].losupdatedelay=.2;
+ for(j=0;j<numplayers;j++){
+ if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype){
+ if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
+ if(findDistancefast(&player[i].coords,&player[j].coords)<400)
+ if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
+ if(player[j].coords.y<player[i].coords.y+5||player[j].onterrain)
+ if((-1==checkcollide(DoRotation(player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position,0,player[i].rotation,0)*player[i].scale+player[i].coords,DoRotation(player[j].skeleton.joints[player[j].skeleton.jointlabels[head]].position,0,player[j].rotation,0)*player[j].scale+player[j].coords)&&!player[j].isWallJump())||(player[j].targetanimation==hanganim&&normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[j].coords;
+ player[i].lastseentime=12;
+ }
+ }
+ }
+ }
+ }
+ if(player[i].aitype==attacktypecutoff&&musictype!=2){
+ if(player[i].creature!=wolftype){
+ player[i].stunned=.6;
+ player[i].surprised=.6;
+ }
+ }
+ }
+
+ if(player[i].aitype!=passivetype&&leveltime>.5){
+ player[i].howactive=typeactive;
+ }
+
+ if(player[i].aitype==passivetype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].losupdatedelay-=multiplier;
+ player[i].lastseentime+=multiplier;
+ player[i].pausetime-=multiplier;
+ if(player[i].lastseentime>1)player[i].lastseentime=1;
+
+ if(player[i].aiupdatedelay<0){
+ if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0){
+ rotatetarget=player[i].waypoints[player[i].waypoint]-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+
+ if(findDistancefastflat(&player[i].coords,&player[i].waypoints[player[i].waypoint])<1){
+ if(player[i].waypointtype[player[i].waypoint]==wppause)player[i].pausetime=4;
+ player[i].waypoint++;
+ if(player[i].waypoint>player[i].numwaypoints-1)player[i].waypoint=0;
+
+ }
+ }
+
+ if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0)player[i].forwardkeydown=1;
+ else player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)player[i].targetrotation+=90;
+ else player[i].targetrotation-=90;
+ }
+ }
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))player[i].jumpkeydown=1;
+
+
+ if(!editorenabled){
+ if(player[i].howactive<typesleeping)
+ if(numenvsounds>0&&(tutoriallevel!=1||cananger)&&hostile)
+ for(j=0;j<numenvsounds;j++){
+ if(findDistancefast(&player[i].coords,&envsound[j])<2*(envsoundvol[j]+envsoundvol[j]*(player[i].creature==rabbittype)*3)){
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+
+ if(player[i].howactive==typesleeping)
+ if(numenvsounds>0&&(tutoriallevel!=1||cananger)&&hostile)
+ for(j=0;j<numenvsounds;j++){
+ if(envsoundvol[j]>14)
+ if(findDistancefast(&player[i].coords,&envsound[j])<2*((envsoundvol[j]-14)+(envsoundvol[j]-14)*(player[i].creature==rabbittype)*3)){
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+
+ if(player[i].aitype!=passivetype){
+ if(player[i].howactive==typesleeping){
+ player[i].targetanimation=getupfromfrontanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ }
+
+ player[i].howactive=typeactive;
+ }
+ }
+
+ if(player[i].howactive<typesleeping&&((tutoriallevel!=1||cananger)&&hostile)&&!player[0].dead&&findDistancefast(&player[i].coords,&player[0].coords)<400&&player[i].occluded<25){
+ if(findDistancefast(&player[i].coords,&player[0].coords)<12&&animation[player[0].targetanimation].height!=lowheight&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<30&&animation[player[0].targetanimation].height==highheight&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+
+ if(player[i].creature==wolftype){
+ XYZ windsmell;
+ float smelldistance;
+ smelldistance=50;
+ for(j=0;j<numplayers;j++){
+ if(j==0||(player[j].dead&&player[j].bloodloss>0)){
+ if(j==0&&player[j].num_weapons>0){
+ if(weapons.bloody[player[j].weaponids[0]])smelldistance=100;
+ if(player[j].num_weapons==2)
+ if(weapons.bloody[player[j].weaponids[1]])smelldistance=100;
+ }
+ if(j!=0){
+ smelldistance=100;
+ }
+ windsmell=windvector;
+ Normalise(&windsmell);
+ windsmell=windsmell*2+player[j].coords;
+ if(findDistancefast(&player[i].coords,&windsmell)<smelldistance&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+ }
+
+ if(player[i].howactive<typesleeping&&player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
+ player[i].losupdatedelay=.2;
+ for(j=0;j<numplayers;j++){
+ if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype){
+ if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
+ if(findDistancefast(&player[i].coords,&player[j].coords)<400)
+ if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
+ if((-1==checkcollide(DoRotation(player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position,0,player[i].rotation,0)*player[i].scale+player[i].coords,DoRotation(player[j].skeleton.joints[player[j].skeleton.jointlabels[head]].position,0,player[j].rotation,0)*player[j].scale+player[j].coords)&&!player[j].isWallJump())||(player[j].targetanimation==hanganim&&normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
+ player[i].lastseentime-=.2;
+ if(j==0&&animation[player[j].targetanimation].height==lowheight)player[i].lastseentime-=.4;
+ else player[i].lastseentime-=.6;
+ }
+ if(player[i].lastseentime<=0){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[j].coords;
+ player[i].lastseentime=12;
+ }
+ }
+ }
+ }
+ }
+ if(player[i].aitype==attacktypecutoff&&musictype!=2){
+ if(player[i].creature!=wolftype){
+ player[i].stunned=.6;
+ player[i].surprised=.6;
+ }
+ if(player[i].creature==wolftype){
+ player[i].stunned=.47;
+ player[i].surprised=.47;
+ }
+ numseen++;
+ }
+ }
+
+ if(player[i].aitype==searchtype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].losupdatedelay-=multiplier;
+ if(!player[i].pause)player[i].lastseentime-=multiplier;
+ player[i].lastchecktime-=multiplier;
+
+ if(player[i].isRun()&&!player[i].onground){
+ if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
+ test2=player[i].coords+player[i].facing;
+ test2.y+=5;
+ test=player[i].coords+player[i].facing;
+ test.y-=10;
+ j=checkcollide(test2,test,player[i].laststanding);
+ if(j==-1)j=checkcollide(test2,test);
+ if(j==-1){
+ player[i].velocity=0;
+ player[i].targetanimation=player[i].getStop();
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].targetrotation+=180;
+ player[i].stunned=.5;
+ //player[i].aitype=passivetype;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ else player[i].laststanding=j;
+ }
+ }
+ if(player[i].aiupdatedelay<0){
+ rotatetarget=player[i].lastseen-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+ if(findDistancefastflat(&player[i].coords,&player[i].lastseen)<1*(player[i].scale*5)*(player[i].scale*5)||player[i].lastchecktime<0){
+ player[i].forwardkeydown=0;
+ player[i].aiupdatedelay=1;
+ player[i].lastseen.x+=(float(Random()%100)-50)/25;
+ player[i].lastseen.z+=(float(Random()%100)-50)/25;
+ player[i].lastchecktime=3;
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)player[i].targetrotation+=90;
+ else player[i].targetrotation-=90;
+ }
+ }
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))player[i].jumpkeydown=1;
+
+ if(numenvsounds>0&&((tutoriallevel!=1||cananger)&&hostile))
+ for(j=0;j<numenvsounds;j++){
+ if(findDistancefast(&player[i].coords,&envsound[j])<2*(envsoundvol[j]+envsoundvol[j]*(player[i].creature==rabbittype)*3)){
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+
+ if(!player[0].dead&&player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2&&((tutoriallevel!=1||cananger)&&hostile)){
+ player[i].losupdatedelay=.2;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<4&&animation[player[i].targetanimation].height!=lowheight)
+ {player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;}
+ if(abs(Random()%2)||animation[player[i].targetanimation].height!=lowheight)
+ if(findDistancefast(&player[i].coords,&player[0].coords)<400)
+ if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
+ if((-1==checkcollide(DoRotation(player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position,0,player[i].rotation,0)*player[i].scale+player[i].coords,DoRotation(player[0].skeleton.joints[player[0].skeleton.jointlabels[head]].position,0,player[0].rotation,0)*player[0].scale+player[0].coords))||(player[j].targetanimation==hanganim&&normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ }
+ if(player[i].lastseentime<0){
+ //player[i].aitype=passivetype;
+ numescaped++;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ }
+
+ if(player[i].aitype!=gethelptype){
+ player[i].runninghowlong=0;
+ }
+
+ if(player[i].aitype==gethelptype){
+ player[i].runninghowlong+=multiplier;
+ player[i].aiupdatedelay-=multiplier;
+
+ if(player[i].aiupdatedelay<0||player[i].ally==0){
+ player[i].aiupdatedelay=.2;
+
+ int closest;
+ float closestdist;
+ closest=-1;
+ closestdist=-1;
+ float distance;
+
+ if(!player[i].ally){
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&j!=0&&!player[j].dead&&player[j].howactive<typedead1&&!player[j].skeleton.free&&player[j].aitype==passivetype){
+ distance=findDistancefast(&player[i].coords,&player[j].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=j;
+ }
+ closest=j;
+ }
+ }
+ if(closest!=-1)player[i].ally=closest;
+ else player[i].ally=0;
+ player[i].lastseen=player[0].coords;
+ player[i].lastseentime=12;
+ }
+
+
+ player[i].lastchecktime=12;
+ //player[i].lastseentime-=.5;
+
+ facing=player[i].coords;
+ flatfacing=player[player[i].ally].coords;
+ facing.y+=player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position.y*player[i].scale;
+ flatfacing.y+=player[player[i].ally].skeleton.joints[player[player[i].ally].skeleton.jointlabels[head]].position.y*player[player[i].ally].scale;
+ if(-1!=checkcollide(facing,flatfacing))
+ player[i].lastseentime-=.1;
+
+ if(player[i].ally<=0||player[player[i].ally].skeleton.free||player[player[i].ally].aitype!=passivetype||player[i].lastseentime<=0){
+ player[i].aitype=searchtype;
+ player[i].lastseentime=12;
+ }
+
+ if(player[i].ally>0){
+ rotatetarget=player[player[i].ally].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+ if(findDistancefastflat(&player[i].coords,&player[player[i].ally].coords)<3){
+ player[i].aitype=searchtype;
+ player[i].lastseentime=12;
+ player[player[i].ally].aitype=searchtype;
+ if(player[player[i].ally].lastseentime<player[i].lastseentime){
+ player[player[i].ally].lastseen=player[i].lastseen;
+ player[player[i].ally].lastseentime=player[i].lastseentime;
+ player[player[i].ally].lastchecktime=player[i].lastchecktime;
+ }
+ }
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)player[i].targetrotation+=90;
+ else player[i].targetrotation-=90;
+ }
+ }
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))player[i].jumpkeydown=1;
+ }
+
+ if(player[i].aitype==getweapontype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].lastchecktime-=multiplier;
+
+ if(player[i].aiupdatedelay<0){
+ player[i].aiupdatedelay=.2;
+
+ int closest;
+ float closestdist;
+ closest=-1;
+ closestdist=-1;
+ float distance;
+
+ if(player[i].ally<0){
+ for(j=0;j<weapons.numweapons;j++){
+ if(weapons.owner[j]==-1){
+ distance=findDistancefast(&player[i].coords,&weapons.position[j]);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=j;
+ }
+ closest=j;
+ }
+ }
+ if(closest!=-1)player[i].ally=closest;
+ else player[i].ally=-1;
+ }
+
+ player[i].lastseentime=12;
+
+ if(!player[0].dead&&((tutoriallevel!=1||cananger)&&hostile))
+ if(player[i].ally<0||player[i].weaponactive!=-1||player[i].lastchecktime<=0){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ if(!player[0].dead)
+ if(player[i].ally>=0){
+ if(weapons.owner[player[i].ally]!=-1||findDistancefast(&player[i].coords,&weapons.position[player[i].ally])>16){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ rotatetarget=weapons.position[player[i].ally]-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)player[i].targetrotation+=90;
+ else player[i].targetrotation-=90;
+ }
+ }
+ /*if(findDistancefast(&player[i].coords,&weapons.position[player[i].ally])<3){
+ if(abs(Random()%6)){
+ player[i].crouchkeydown=1;
+ if(!findDistancefast(&player[i].coords,&weapons.position[player[i].ally])<1){
+ if(player[i].isRun()){
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].targetanimation=sneakanim;
+ }
+ }
+ else player[i].forwardkeydown=0;
+ }
+ else player[i].crouchkeydown=0;
+ }
+ else player[i].crouchkeydown=0;*/
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=1;
+ player[i].crouchkeydown=0;
+ if(player[i].targetanimation!=crouchremoveknifeanim&&player[i].targetanimation!=removeknifeanim)player[i].throwtogglekeydown=0;
+ player[i].drawkeydown=0;
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))player[i].jumpkeydown=1;
+ }
+
+ if(player[i].aitype==attacktypecutoff){
+ player[i].aiupdatedelay-=multiplier;
+ if(player[i].damage<player[i].damagetolerance*2/3)
+ if((player[0].targetanimation==rabbitkickanim||player[0].targetanimation==knifethrowanim||(player[0].isFlip()&&normaldotproduct(player[0].facing,player[0].coords-player[i].coords)<0))&&!player[0].skeleton.free&&(player[i].aiupdatedelay<.1)){
+ player[i].attackkeydown=0;
+ if(player[i].isIdle())player[i].crouchkeydown=1;
+ if(player[0].targetanimation!=rabbitkickanim&&player[0].weaponactive!=-1){
+ if(weapons.type[player[0].weaponids[0]]==knife){
+ if(player[i].isIdle()||player[i].isCrouch()||player[i].isRun()||player[i].isFlip()){
+ if(abs(Random()%2==0))player[i].targetanimation=backhandspringanim;
+ else player[i].targetanimation=rollanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ player[i].targetrotation+=90*(abs(Random()%2)*2-1);
+ player[i].wentforweapon=0;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim){
+ player[i].targetanimation=flipanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ }
+ }
+ player[i].forwardkeydown=0;
+ player[i].aiupdatedelay=.02;
+ }
+ if(player[0].isFlip()&&!player[0].skeleton.free&&player[0].targetanimation!=walljumprightkickanim&&player[0].targetanimation!=walljumpleftkickanim){
+ if(findDistancefast(&player[0].coords,&player[i].coords)<25)
+ if((1-player[i].damage/player[i].damagetolerance)>.5)player[i].stunned=1;
+ }
+ if(player[i].wentforweapon<3)
+ for(j=0;j<weapons.numweapons;j++){
+ if(player[i].creature!=wolftype)
+ if(player[i].num_weapons==0&&weapons.owner[j]==-1&&weapons.velocity[i].x==0&&weapons.velocity[i].z==0&&weapons.velocity[i].y==0){
+ if(findDistancefast(&player[i].coords,&weapons.position[j])<16){
+ player[i].wentforweapon++;
+ player[i].lastchecktime=6;
+ player[i].aitype=getweapontype;
+ player[i].ally=-1;
+ }
+ }
+ }
+ if(player[i].damage<player[i].damagetolerance/2)
+ if(animation[player[i].targetanimation].height!=highheight)
+ if(player[i].damage<player[i].damagetolerance*.5&&((player[0].targetanimation==walljumprightkickanim||player[0].targetanimation==walljumpleftkickanim)&&((player[i].aiupdatedelay<.15&&difficulty==2)||(player[i].aiupdatedelay<.08&&difficulty!=2)))){
+ player[i].crouchkeydown=1;
+ }
+ if(player[i].isRun()&&!player[i].onground){
+ if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
+ test2=player[i].coords+player[i].facing;
+ test2.y+=5;
+ test=player[i].coords+player[i].facing;
+ test.y-=10;
+ j=checkcollide(test2,test,player[i].laststanding);
+ if(j==-1)j=checkcollide(test2,test);
+ if(j==-1){
+ player[i].velocity=0;
+ player[i].targetanimation=player[i].getStop();
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].targetrotation+=180;
+ player[i].stunned=.5;
+ //player[i].aitype=passivetype;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ else player[i].laststanding=j;
+ }
+ }
+ if(player[0].coords.y>player[i].coords.y+5&&animation[player[0].targetanimation].height!=highheight&&!player[0].onterrain){
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ if(player[i].aiupdatedelay<0&&!animation[player[i].targetanimation].attack&&player[i].targetanimation!=staggerbackhighanim&&player[i].targetanimation!=staggerbackhardanim&&player[i].targetanimation!=backhandspringanim&&player[i].targetanimation!=dodgebackanim){
+ if(player[i].weaponactive==-1&&player[i].num_weapons>0)player[i].drawkeydown=Random()%2;
+ else player[i].drawkeydown=0;
+ player[i].rabbitkickenabled=Random()%2;
+ rotatetarget=player[player[i].aitarget].coords+player[player[i].aitarget].velocity;
+ if(findDistancefast(&player[player[i].aitarget].coords,&player[i].coords)<findDistancefast(&rotatetarget,&player[i].coords))
+ rotatetarget=player[player[i].aitarget].coords+player[player[i].aitarget].velocity*findDistance(&player[player[i].aitarget].coords,&player[i].coords)/findLength(&player[i].velocity)-player[i].coords;
+ else rotatetarget=player[player[i].aitarget].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.2+abs((float)(Random()%100)/1000);
+
+ oldkey=player[i].forwardkeydown;
+ if(findDistancefast(&player[i].coords,&player[0].coords)>5&&(player[0].weaponactive==-1||player[i].weaponactive!=-1))player[i].forwardkeydown=1;
+ else if((findDistancefast(&player[i].coords,&player[0].coords)>16||findDistancefast(&player[i].coords,&player[0].coords)<9)&&player[0].weaponactive!=-1)player[i].forwardkeydown=1;
+ else if(Random()%6==0||(player[i].creature==wolftype&&Random()%3==0))player[i].forwardkeydown=1;
+ else player[i].forwardkeydown=0;
+ if(player[0].dead){
+ player[i].forwardkeydown=0;
+ if(Random()%10==0)player[i].forwardkeydown=1;
+ if(Random()%100==0){
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ }
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ /*for(j=0;j<numplayers;j++){
+ if(player[j].victim->id==i&&(player[j].targetanimation==spinkickanim&&player[j].targetframe<3)){
+ player[i].crouchkeydown=1;
+ }
+ }*/
+ if(Random()%2==0/*||player[0].weaponactive!=-1*/||player[i].weaponactive!=-1||player[i].creature==wolftype)player[i].attackkeydown=1;
+ else player[i].attackkeydown=0;
+ if((player[i].isRun())&&Random()%6&&findDistancefast(&player[i].coords,&player[0].coords)>7)player[i].attackkeydown=0;
+ //if(player[i].attackkeydown&&findDistancefast(&player[i].coords,&player[0].coords)<3&&player[i].targetanimation!=runanim&&!player[0].skeleton.free)player[i].crouchkeydown=1;
+ /*if(player[0].targetanimation==rabbitkickanim&&!player[0].skeleton.free){
+ player[i].attackkeydown=0;
+ if(player[i].isIdle())player[i].crouchkeydown=1;
+ player[i].forwardkeydown=0;
+ player[i].aiupdatedelay=.02;
+ }*/
+
+ if(player[i].aitype!=playercontrolled&&(player[i].isIdle()||player[i].isCrouch()||player[i].isRun())){
+ target=-2;
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&!player[j].skeleton.free&&player[j].hasvictim&&((tutoriallevel==1&&reversaltrain)||(Random()%2==0&&difficulty==2)||(Random()%4==0&&difficulty==1)||(Random()%8==0&&difficulty==0)||(player[j].lastattack2==player[j].targetanimation&&player[j].lastattack3==player[j].targetanimation&&(Random()%2==0||difficulty==2))||((player[i].isIdle()||player[i].isRun())&&player[j].weaponactive!=-1)||(player[j].targetanimation==swordslashanim&&player[i].weaponactive!=-1)||player[j].targetanimation==staffhitanim||player[j].targetanimation==staffspinhitanim)){
+ if(findDistancefast(&player[j].coords,&player[j].victim->coords)<4&&player[j].victim==&player[i]&&(player[j].targetanimation==sweepanim||player[j].targetanimation==spinkickanim||player[j].targetanimation==staffhitanim||player[j].targetanimation==staffspinhitanim||player[j].targetanimation==winduppunchanim||player[j].targetanimation==upunchanim||player[j].targetanimation==wolfslapanim||player[j].targetanimation==knifeslashstartanim||((player[j].targetanimation==swordslashanim)&&(findDistancefast(&player[j].coords,&player[i].coords)<2||(player[i].weaponactive!=-1))))){
+ if(target>=0)target=-1;
+ else target=j;
+ }
+ }
+ }
+ if(target>=0)player[target].Reverse();
+ }
+
+ if(player[i].collided<1)player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5)||(findDistancefast(&player[i].coords,&player[0].coords)>400&&player[i].onterrain&&player[i].creature==rabbittype))player[i].jumpkeydown=1;
+ if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
+ player[0].jumpkeydown=0;
+ if(player[0].targetanimation==jumpdownanim&&findDistancefast(&player[0].coords,&player[i].coords)<40)player[i].crouchkeydown=1;
+ if(player[i].jumpkeydown)player[i].attackkeydown=0;
+ //if(animation[player[i].targetanimation].attack==reversed)player[i].crouchkeydown=1;
+
+ if(tutoriallevel==1){
+ if(!canattack)player[i].attackkeydown=0;
+ }
+
+
+ facing=player[i].coords;
+ flatfacing=player[0].coords;
+ facing.y+=player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position.y*player[i].scale;
+ flatfacing.y+=player[0].skeleton.joints[player[0].skeleton.jointlabels[head]].position.y*player[0].scale;
+ if(player[i].occluded>=2)
+ if(-1!=checkcollide(facing,flatfacing)){
+ if(!player[i].pause)player[i].lastseentime-=.2;
+ if(player[i].lastseentime<=0&&(player[i].creature!=wolftype||player[i].weaponstuck==-1)){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[0].coords;
+ player[i].lastseentime=12;
+ }
+ }
+ else player[i].lastseentime=1;
+ }
+ }
+ if(animation[player[0].targetanimation].height==highheight&&(player[i].aitype==attacktypecutoff||player[i].aitype==searchtype)){
+ if(player[0].coords.y>terrain.getHeight(player[0].coords.x,player[0].coords.z)+10){
+ test=player[0].coords;
+ test.y-=40;
+ if(-1==checkcollide(player[0].coords,test))player[i].stunned=1;
+ }
+ }
+ // NOTE: Ask about logic of this call : NOTE
+ if((player[i].aitype==passivetype && !(player[i].numwaypoints>1)) ||
+ player[i].stunned>0 ||
+ (player[i].pause && (player[i].damage > player[i].superpermanentdamage)))
+ {
+ if(/*player[i].aitype==attacktypecutoff&&*/player[i].pause)player[i].lastseentime=1;
+ player[i].targetrotation=player[i].rotation;
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+ }
+
+
+ facing=0;
+ facing.z=-1;
+
+ flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
+ facing=flatfacing;
+
+ if(player[i].aitype==attacktypecutoff){
+ rotatetarget=player[0].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetheadrotation=-asin(0-rotatetarget.x);
+ player[i].targetheadrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetheadrotation=180-player[i].targetheadrotation;
+
+ player[i].targetheadrotation*=-1;
+ player[i].targetheadrotation+=180;
+ //player[i].targetheadrotation2=0;
+ player[i].targetheadrotation2=-asin(rotatetarget.y)*360/6.28;
+ }
+ else if(player[i].howactive>=typesleeping){
+ player[i].targetheadrotation=player[i].targetrotation;
+ player[i].targetheadrotation2=0;
+ }
+ else {
+ if(player[i].interestdelay<=0){
+ player[i].interestdelay=.7+(float)(abs(Random()%100))/100;
+ player[i].headtarget=player[i].coords;
+ player[i].headtarget.x+=(float)(abs(Random()%200)-100)/100;
+ player[i].headtarget.z+=(float)(abs(Random()%200)-100)/100;
+ player[i].headtarget.y+=(float)(abs(Random()%200)-100)/300;
+ player[i].headtarget+=player[i].facing*1.5;
+ }
+ rotatetarget=player[i].headtarget-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetheadrotation=-asin(0-rotatetarget.x);
+ player[i].targetheadrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetheadrotation=180-player[i].targetheadrotation;
+
+ player[i].targetheadrotation*=-1;
+ player[i].targetheadrotation+=180;
+ player[i].targetheadrotation2=-asin(rotatetarget.y)*360/6.28;
+ }
+ //if(whichlevel==2)player[i].jumpkeydown=0;
+ }
+ if(animation[player[i].targetanimation].attack==reversed){
+ //player[i].targetrotation=player[i].rotation;
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].attackkeydown=0;
+ //player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+ }
+
+ if(indialogue!=-1){
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].drawkeydown=0;
+ player[i].throwkeydown=0;
+ }
+
+ if(player[i].collided<-.3)player[i].collided=-.3;
+ if(player[i].collided>1)player[i].collided=1;
+ player[i].collided-=multiplier*4;
+ player[i].whichdirectiondelay-=multiplier;
+ if(player[i].avoidcollided<-.3||player[i].whichdirectiondelay<=0){
+ player[i].avoidcollided=-.3;
+ player[i].whichdirection=abs(Random()%2);
+ player[i].whichdirectiondelay=.4;
+ }
+ if(player[i].avoidcollided>1)player[i].avoidcollided=1;
+ player[i].avoidcollided-=multiplier/4;
+ if(!player[i].skeleton.free)player[i].stunned-=multiplier;
+ if(!player[i].skeleton.free)player[i].surprised-=multiplier;
+ if(player[i].surprised<=0&&player[i].aitype==attacktypecutoff&&i!=0&&!player[i].dead&&!player[i].skeleton.free&&animation[player[i].targetanimation].attack==neutral)numresponded=1;
+
+ if(!player[i].throwkeydown){
+ player[i].throwtogglekeydown=0;
+ }
+ if(player[i].throwkeydown&&!player[i].throwtogglekeydown){
+ if(player[i].weaponactive==-1&&player[i].num_weapons<2&&(player[i].isIdle()||player[i].isCrouch()||player[i].targetanimation==sneakanim||player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim||player[i].isFlip()||player[i].isFlip()||player[i].aitype!=playercontrolled)){
+ for(j=0;j<weapons.numweapons;j++){
+ if(((weapons.velocity[j].x==0&&weapons.velocity[j].y==0&&weapons.velocity[j].z==0)||player[i].aitype==playercontrolled)&&weapons.owner[j]==-1&&player[i].weaponactive==-1)
+ if(findDistancefastflat(&player[i].coords,&weapons.position[j])<2){
+ if(findDistancefast(&player[i].coords,&weapons.position[j])<2){
+ if(player[i].isCrouch()||player[i].targetanimation==sneakanim||player[i].isRun()||player[i].isIdle()||player[i].aitype!=playercontrolled){
+ player[i].throwtogglekeydown=1;
+ player[i].targetanimation=crouchremoveknifeanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ rotatetarget=weapons.position[j]-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ player[i].hasvictim=0;
+ }
+ if(player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim){
+ player[i].throwtogglekeydown=1;
+ player[i].hasvictim=0;
+
+ //for(i=0;i<weapons.numweapons;i++){
+ if((((weapons.velocity[j].x==0&&weapons.velocity[j].y==0&&weapons.velocity[j].z==0)||player[i].aitype==playercontrolled)&&weapons.owner[j]==-1)||(player[i].victim&&weapons.owner[j]==player[i].victim->id))
+ if(findDistancefastflat(&player[i].coords,&weapons.position[j])<2&&player[i].weaponactive==-1){
+ if(findDistancefast(&player[i].coords,&weapons.position[j])<1||player[i].victim){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[i].coords.x;
+ gLoc[1]=player[i].coords.y;
+ gLoc[2]=player[i].coords.z;
+ vel[0]=player[i].velocity.x;
+ vel[1]=player[i].velocity.y;
+ vel[2]=player[i].velocity.z;
+ if(weapons.type[j]!=staff){
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+
+ player[i].weaponactive=0;
+ weapons.owner[j]=player[i].id;
+ if(player[i].num_weapons>0){
+ player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
+ }
+ player[i].num_weapons++;
+ player[i].weaponids[0]=j;
+ }
+ }
+ //}
+ }
+ }
+ else if ((player[i].isIdle()||player[i].isFlip()||player[i].aitype!=playercontrolled)&&findDistancefast(&player[i].coords,&weapons.position[j])<5&&player[i].coords.y<weapons.position[j].y){
+ if(!player[i].isFlip()){
+ player[i].throwtogglekeydown=1;
+ player[i].targetanimation=removeknifeanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ rotatetarget=weapons.position[j]-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ }
+ if(player[i].isFlip()){
+ player[i].throwtogglekeydown=1;
+ player[i].hasvictim=0;
+
+ for(k=0;k<weapons.numweapons;k++){
+ if(player[i].weaponactive==-1)
+ if((((weapons.velocity[k].x==0&&weapons.velocity[k].y==0&&weapons.velocity[k].z==0)||player[i].aitype==playercontrolled)&&weapons.owner[k]==-1)||(player[i].victim&&weapons.owner[k]==player[i].victim->id))
+ if(findDistancefastflat(&player[i].coords,&weapons.position[k])<3&&player[i].weaponactive==-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[i].coords.x;
+ gLoc[1]=player[i].coords.y;
+ gLoc[2]=player[i].coords.z;
+ vel[0]=player[i].velocity.x;
+ vel[1]=player[i].velocity.y;
+ vel[2]=player[i].velocity.z;
+ if(weapons.type[k]!=staff){
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+
+ player[i].weaponactive=0;
+ weapons.owner[k]=player[i].id;
+ if(player[i].num_weapons>0){
+ player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
+ }
+ player[i].num_weapons++;
+ player[i].weaponids[0]=k;
+ }
+ }
+ }
+ }
+ }
+ }
+ if(player[i].isCrouch()||player[i].targetanimation==sneakanim||player[i].isRun()||player[i].isIdle()||player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim){
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(player[i].weaponactive==-1)
+ if(j!=i)
+ if(player[j].num_weapons&&player[j].skeleton.free&&findDistancefast(&player[i].coords,&player[j].coords)<2/*&&player[j].dead*/&&(((player[j].skeleton.forward.y<0&&player[j].weaponstuckwhere==0)||(player[j].skeleton.forward.y>0&&player[j].weaponstuckwhere==1))||player[j].weaponstuck==-1||player[j].num_weapons>1)){
+ if(player[i].targetanimation!=rollanim&&player[i].targetanimation!=backhandspringanim){
+ player[i].throwtogglekeydown=1;
+ player[i].victim=&player[j];
+ player[i].hasvictim=1;
+ player[i].targetanimation=crouchremoveknifeanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ rotatetarget=player[j].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+ }
+ if(player[i].targetanimation==rollanim||player[i].targetanimation==backhandspringanim){
+ player[i].throwtogglekeydown=1;
+ player[i].victim=&player[j];
+ player[i].hasvictim=1;
+ int k = player[j].weaponids[0];
+ if(player[i].hasvictim){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[i].coords.x;
+ gLoc[1]=player[i].coords.y;
+ gLoc[2]=player[i].coords.z;
+ vel[0]=player[i].velocity.x;
+ vel[1]=player[i].velocity.y;
+ vel[2]=player[i].velocity.z;
+ bool fleshstuck;
+ fleshstuck=0;
+ if(player[i].victim->weaponstuck!=-1){
+ if(player[i].victim->weaponids[player[i].victim->weaponstuck]==k){
+ fleshstuck=1;
+ }
+ }
+ if(!fleshstuck){
+ if(weapons.type[k]!=staff){
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+ }
+ if(fleshstuck){
+ PlaySoundEx( fleshstabremovesound, samp[fleshstabremovesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabremovesound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabremovesound], 128);
+ FSOUND_SetPaused(channels[fleshstabremovesound], FALSE);
+ }
+
+ player[i].weaponactive=0;
+ if(weapons.owner[k]!=-1){
+ if(player[i].victim->num_weapons==1)player[i].victim->num_weapons=0;
+ else player[i].victim->num_weapons=1;
+
+ player[i].victim->skeleton.longdead=0;
+ player[i].victim->skeleton.free=1;
+ player[i].victim->skeleton.broken=0;
+
+ for(int l=0;l<player[i].victim->skeleton.num_joints;l++){
+ player[i].victim->skeleton.joints[l].velchange=0;
+ player[i].victim->skeleton.joints[l].locked=0;
+ }
+
+ XYZ relative;
+ relative=0;
+ relative.y=10;
+ Normalise(&relative);
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.position[k];
+ if(player[i].victim->weaponstuck!=-1){
+ if(player[i].victim->weaponids[player[i].victim->weaponstuck]==k){
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .8, .3);
+ weapons.bloody[k]=2;
+ weapons.blooddrip[k]=5;
+ player[i].victim->weaponstuck=-1;
+ player[i].victim->bloodloss+=2000;
+ player[i].victim->DoDamage(2000);
+ }
+ }
+ if(player[i].victim->num_weapons>0){
+ if(player[i].victim->weaponstuck!=0&&player[i].victim->weaponstuck!=-1)player[i].victim->weaponstuck=0;
+ if(player[i].victim->weaponids[0]==k)
+ player[i].victim->weaponids[0]=player[i].victim->weaponids[player[i].victim->num_weapons];
+ }
+
+ player[i].victim->weaponactive=-1;
+
+ player[i].victim->skeleton.joints[player[i].victim->skeleton.jointlabels[abdomen]].velocity+=relative*6;
+ player[i].victim->skeleton.joints[player[i].victim->skeleton.jointlabels[neck]].velocity+=relative*6;
+ player[i].victim->skeleton.joints[player[i].victim->skeleton.jointlabels[rightshoulder]].velocity+=relative*6;
+ player[i].victim->skeleton.joints[player[i].victim->skeleton.jointlabels[leftshoulder]].velocity+=relative*6;
+ }
+ weapons.owner[k]=i;
+ if(player[i].num_weapons>0){
+ player[i].weaponids[player[i].num_weapons]=player[i].weaponids[0];
+ }
+ player[i].num_weapons++;
+ player[i].weaponids[0]=k;
+ }
+ }
+ }
+ }
+ }
+ }
+ if(player[i].weaponactive!=-1&&player[i].aitype==playercontrolled){
+ if(weapons.type[player[i].weaponids[0]]==knife){
+ if(player[i].isIdle()||player[i].isRun()||player[i].isCrouch()||player[i].targetanimation==sneakanim||player[i].isFlip())
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(i!=j)
+ if(tutoriallevel!=1||tutorialstage==49)
+ if(hostile)
+ if(normaldotproduct(player[i].facing,player[i].coords-player[j].coords)<0&&findDistancefast(&player[i].coords,&player[j].coords)<100&&findDistancefast(&player[i].coords,&player[j].coords)>1.5&&!player[j].skeleton.free&&-1==checkcollide(DoRotation(player[j].skeleton.joints[player[j].skeleton.jointlabels[head]].position,0,player[j].rotation,0)*player[j].scale+player[j].coords,DoRotation(player[i].skeleton.joints[player[i].skeleton.jointlabels[head]].position,0,player[i].rotation,0)*player[i].scale+player[i].coords)){
+ if(!player[i].isFlip()){
+ player[i].throwtogglekeydown=1;
+ player[i].victim=&player[j];
+ player[i].targetanimation=knifethrowanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ rotatetarget=player[j].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[i].targetrotation=-asin(0-rotatetarget.x);
+ player[i].targetrotation*=360/6.28;
+ if(rotatetarget.z<0)player[i].targetrotation=180-player[i].targetrotation;
+
+ player[i].targettilt2=-asin(rotatetarget.y)*360/6.28;
+ }
+ if(player[i].isFlip()){
+ if(player[i].weaponactive!=-1){
+ player[i].throwtogglekeydown=1;
+ player[i].victim=&player[j];
+ XYZ aim;
+ weapons.owner[player[i].weaponids[0]]=-1;
+ aim=player[i].victim->coords+DoRotation(player[i].victim->skeleton.joints[player[i].victim->skeleton.jointlabels[abdomen]].position,0,player[i].victim->rotation,0)*player[i].victim->scale+player[i].victim->velocity*findDistance(&player[i].victim->coords,&player[i].coords)/50-(player[i].coords+DoRotation(player[i].skeleton.joints[player[i].skeleton.jointlabels[righthand]].position,0,player[i].rotation,0)*player[i].scale);
+ Normalise(&aim);
+
+ aim=DoRotation(aim,(float)abs(Random()%30)-15,(float)abs(Random()%30)-15,0);
+
+ weapons.velocity[player[i].weaponids[0]]=aim*50;
+ weapons.tipvelocity[player[i].weaponids[0]]=aim*50;
+ weapons.missed[player[i].weaponids[0]]=0;
+ weapons.freetime[player[i].weaponids[0]]=0;
+ weapons.firstfree[player[i].weaponids[0]]=1;
+ weapons.physics[player[i].weaponids[0]]=0;
+ player[i].num_weapons--;
+ if(player[i].num_weapons){
+ player[i].weaponids[0]=player[i].weaponids[player[i].num_weapons];
+ }
+ player[i].weaponactive=-1;
+ }
+ }
+ }
+ }
+ }
+ }
+ if(player[i].weaponactive!=-1&&player[i].aitype==playercontrolled){
+ if(player[i].isCrouch()||player[i].targetanimation==sneakanim)
+ {
+ player[i].throwtogglekeydown=1;
+ weapons.owner[player[i].weaponids[0]]=-1;
+ weapons.velocity[player[i].weaponids[0]]=player[i].velocity*.2;
+ if(weapons.velocity[player[i].weaponids[0]].x==0)weapons.velocity[player[i].weaponids[0]].x=.1;
+ weapons.tipvelocity[player[i].weaponids[0]]=weapons.velocity[player[i].weaponids[0]];
+ weapons.missed[player[i].weaponids[0]]=1;
+ weapons.freetime[player[i].weaponids[0]]=0;
+ weapons.firstfree[player[i].weaponids[0]]=1;
+ weapons.physics[player[i].weaponids[0]]=1;
+ player[i].num_weapons--;
+ if(player[i].num_weapons){
+ player[i].weaponids[0]=player[i].weaponids[player[i].num_weapons];
+ if(player[i].weaponstuck==player[i].num_weapons)player[i].weaponstuck=0;
+ }
+
+ player[i].weaponactive=-1;
+ for(j=0;j<numplayers;j++){
+ player[j].wentforweapon=0;
+ }
+ }
+ }
+
+ }
+
+ if(i==0||!player[0].dead||player[i].weaponactive!=-1)
+ if((player[i].drawkeydown&&!player[i].drawtogglekeydown)||(player[i].num_weapons==2&&player[i].weaponactive==-1&&player[i].isIdle())||(player[0].dead&&player[i].weaponactive!=-1&&i!=0)){
+ //Setenvironment(1-environment);
+ bool isgood;
+ isgood=1;
+ if(player[i].weaponactive!=-1){
+ if(weapons.type[player[i].weaponids[player[i].weaponactive]]==staff)isgood=0;
+ }
+ if(/*(player[i].weaponactive==-1||player[i].num_weapons==1)&&*/isgood&&player[i].creature!=wolftype){
+ if(player[i].isIdle()&&player[i].num_weapons&&weapons.type[player[i].weaponids[0]]==knife){
+ player[i].targetanimation=drawrightanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].drawtogglekeydown=1;
+ }
+ if((player[i].isIdle()||(player[i].aitype!=playercontrolled&&player[0].weaponactive!=-1&&player[i].isRun()))&&player[i].num_weapons&&weapons.type[player[i].weaponids[0]]==sword){
+ player[i].targetanimation=drawleftanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].drawtogglekeydown=1;
+ }
+ if(player[i].isCrouch()&&player[i].num_weapons&&weapons.type[player[i].weaponids[0]]==knife){
+ player[i].targetanimation=crouchdrawrightanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].drawtogglekeydown=1;
+ }
+ }
+ }
+ if(player[i].isCrouch()&&weapons.bloody[player[i].weaponids[player[i].weaponactive]]&&bloodtoggle&&player[i].onterrain&&player[i].num_weapons&&player[i].weaponactive!=-1&&player[i].attackkeydown){
+ if(weapons.bloody[player[i].weaponids[player[i].weaponactive]]&&player[i].onterrain&&bloodtoggle&&musictype!=stream_music2){
+ if(weapons.type[player[i].weaponids[player[i].weaponactive]]==knife)player[i].targetanimation=crouchstabanim;
+ if(weapons.type[player[i].weaponids[player[i].weaponactive]]==sword)player[i].targetanimation=swordgroundstabanim;
+ player[i].targetframe=0;
+ player[i].target=0;
+ player[i].hasvictim=0;
+ //player[i].attacktogglekeydown=1;
+ }
+ }
+
+ if(!player[i].drawkeydown){
+ player[i].drawtogglekeydown=0;
+ }
+
+ if(i==0){
+ absflatfacing=0;
+ absflatfacing.z=-1;
+
+ absflatfacing=DoRotation(absflatfacing,0,-rotation,0);
+ }
+ else absflatfacing=flatfacing;
+
+ if(indialogue!=-1){
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].drawkeydown=0;
+ player[i].throwkeydown=0;
+ }
+ movekey=0;
+ //Do controls
+ if(!animation[player[i].targetanimation].attack&&player[i].targetanimation!=staggerbackhighanim&&player[i].targetanimation!=staggerbackhardanim&&player[i].targetanimation!=backhandspringanim&&player[i].targetanimation!=dodgebackanim){
+ if(!player[i].forwardkeydown){
+ player[i].forwardstogglekeydown=0;
+ }
+ if(player[i].crouchkeydown){
+ //Crouch
+ target=-2;
+ if(i==0){
+ player[i].superruntoggle=1;
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&!player[j].skeleton.free&&player[j].aitype==passivetype){
+ if(findDistancefast(&player[j].coords,&player[i].coords)<16){
+ player[i].superruntoggle=0;
+ }
+ }
+ }
+ }
+
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&!player[j].skeleton.free&&player[j].victim&&player[i].lowreversaldelay<=0){
+ if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&player[j].victim==&player[i]&&(player[j].targetanimation==sweepanim||player[j].targetanimation==upunchanim||player[j].targetanimation==wolfslapanim||((player[j].targetanimation==swordslashanim||player[j].targetanimation==knifeslashstartanim||player[j].targetanimation==staffhitanim||player[j].targetanimation==staffspinhitanim)&&findDistancefast(&player[j].coords,&player[i].coords)<2))){
+ if(target>=0)target=-1;
+ else target=j;
+ }
+ }
+ }
+ if(target>=0)player[target].Reverse();
+ player[i].lowreversaldelay=.5;
+
+ if(player[i].isIdle()){
+ player[i].targetanimation=player[i].getCrouch();
+ player[i].target=0;
+ player[i].targetframe=0;
+ player[i].transspeed=10;
+ }
+ if(player[i].isRun()||(player[i].isStop()&&(player[i].leftkeydown||player[i].rightkeydown||player[i].forwardkeydown||player[i].backkeydown))){
+ player[i].targetanimation=rollanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ player[i].transspeed=20;
+ }
+ }
+ if(!player[i].crouchkeydown){
+ //Uncrouch
+ if(!player[i].isRun()&&player[i].targetanimation!=sneakanim&&i==0)player[i].superruntoggle=0;
+ target=-2;
+ if(player[i].isCrouch()){
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&!player[j].skeleton.free&&player[j].victim&&player[i].highreversaldelay<=0){
+ if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&player[j].victim==&player[i]&&(player[j].targetanimation==spinkickanim)&&player[i].isCrouch()){
+ if(target>=0)target=-1;
+ else target=j;
+ }
+ }
+ }
+ if(target>=0)player[target].Reverse();
+ player[i].highreversaldelay=.5;
+
+ if(player[i].isCrouch()){
+ if(!player[i].wasCrouch()){
+ player[i].currentanimation=player[i].getCrouch();
+ player[i].currentframe=0;
+ }
+ player[i].target=0;
+ player[i].targetanimation=player[i].getIdle();
+ player[i].targetframe=0;
+ player[i].transspeed=10;
+ }
+ }
+ if(player[i].targetanimation==sneakanim){
+ player[i].targetanimation=player[i].getIdle();
+ player[i].target=0;
+ player[i].targetframe=0;
+ player[i].transspeed=10;
+ }
+ }
+ if(player[i].forwardkeydown){
+ if(player[i].isIdle()||(player[i].isStop()&&player[i].targetrotation==player[i].rotation)||(player[i].isLanding()&&player[i].targetframe>0&&!player[i].jumpkeydown)||(player[i].isLandhard()&&player[i].targetframe>0&&!player[i].jumpkeydown&&player[i].crouchkeydown)){
+ if(player[i].aitype==passivetype)player[i].targetanimation=walkanim;
+ else player[i].targetanimation=player[i].getRun();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].isCrouch()){
+ player[i].targetanimation=sneakanim;
+ if(player[i].wasCrouch())player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].targetanimation==hanganim/*&&(!player[i].forwardstogglekeydown||player[i].aitype!=playercontrolled)*/){
+ player[i].targetanimation=climbanim;
+ player[i].target=0;
+ player[i].targetframe=1;
+ player[i].jumpclimb=1;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
+ player[i].velocity+=absflatfacing*5*multiplier;
+ }
+ player[i].forwardstogglekeydown=1;
+ movekey=1;
+ }
+ if (player[i].rightkeydown){
+ if(player[i].isIdle()||(player[i].isStop()&&player[i].targetrotation==player[i].rotation)||(player[i].isLanding()&&player[i].targetframe>0&&!player[i].jumpkeydown)||(player[i].isLandhard()&&player[i].targetframe>0&&!player[i].jumpkeydown&&player[i].crouchkeydown)){
+ player[i].targetanimation=player[i].getRun();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].isCrouch()){
+ player[i].targetanimation=sneakanim;
+ if(player[i].wasCrouch()) player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
+ player[i].velocity+=DoRotation(absflatfacing*5*multiplier,0,-90,0);
+ }
+ player[i].targetrotation-=90;
+ if(player[i].forwardkeydown)player[i].targetrotation+=45;
+ if(player[i].backkeydown)player[i].targetrotation-=45;
+ movekey=1;
+ }
+ if ( player[i].leftkeydown){
+ if(player[i].isIdle()||(player[i].isStop()&&player[i].targetrotation==player[i].rotation)||(player[i].isLanding()&&player[i].targetframe>0&&!player[i].jumpkeydown)||(player[i].isLandhard()&&player[i].targetframe>0&&!player[i].jumpkeydown&&player[i].crouchkeydown)){
+ player[i].targetanimation=player[i].getRun();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].isCrouch()){
+ player[i].targetanimation=sneakanim;
+ if(player[i].wasCrouch())player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
+ player[i].velocity-=DoRotation(absflatfacing*5*multiplier,0,-90,0);
+ }
+ player[i].targetrotation+=90;
+ if(player[i].forwardkeydown)player[i].targetrotation-=45;
+ if(player[i].backkeydown)player[i].targetrotation+=45;
+ movekey=1;
+ }
+ if(player[i].backkeydown){
+ if(player[i].isIdle()||(player[i].isStop()&&player[i].targetrotation==player[i].rotation)||(player[i].isLanding()&&player[i].targetframe>0&&!player[i].jumpkeydown)||(player[i].isLandhard()&&player[i].targetframe>0&&!player[i].jumpkeydown&&player[i].crouchkeydown)){
+ player[i].targetanimation=player[i].getRun();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].isCrouch()){
+ player[i].targetanimation=sneakanim;
+ if(player[i].wasCrouch())player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip()){
+ player[i].velocity-=absflatfacing*5*multiplier;
+ }
+ if(player[i].targetanimation==hanganim){
+ player[i].currentanimation=jumpdownanim;
+ player[i].targetanimation=jumpdownanim;
+ player[i].target=0;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ player[i].velocity=0;
+ player[i].velocity.y+=gravity;
+ player[i].coords.y-=1.4;
+ player[i].grabdelay=1;
+ }
+ if ( !player[i].leftkeydown&&!player[i].rightkeydown)
+ player[i].targetrotation+=180;
+ movekey=1;
+ }
+ if((player[i].jumpkeydown&&!player[i].jumpclimb)||player[i].jumpstart){
+ if((((player[i].isLanding()&&player[i].targetframe>=3)||player[i].isRun()||player[i].targetanimation==walkanim||player[i].isCrouch()||player[i].targetanimation==sneakanim)&&player[i].jumppower>1)&&((player[i].targetanimation!=rabbitrunninganim&&player[i].targetanimation!=wolfrunninganim)||i!=0)){
+ player[i].jumpstart=0;
+ player[i].targetanimation=jumpupanim;
+ player[i].target=0;
+ player[i].targetframe=0;
+ player[i].rotation=player[i].targetrotation;
+ player[i].transspeed=20;
+ player[i].FootLand(0,1);
+ player[i].FootLand(1,1);
+
+ facing=0;
+ facing.z=-1;
+ flatfacing=DoRotation(facing,0,player[i].targetrotation+180,0);
+
+ if(movekey)player[i].velocity=flatfacing*player[i].speed*45*player[i].scale;
+ if(!movekey)player[i].velocity=0;
+
+ //Dodge sweep?
+ target=-2;
+ if(numplayers>1)
+ for(j=0;j<numplayers;j++){
+ if(j!=i&&!player[j].skeleton.free&&player[j].victim){
+ if(findDistancefast(&player[j].coords,&player[j].victim->coords)<3&&player[j].victim==&player[i]&&(player[j].targetanimation==sweepanim)){
+ if(target>=0)target=-1;
+ else target=j;
+ }
+ }
+ }
+ if(target>=0)player[i].velocity.y=1;
+ else if(player[i].crouchkeydown||player[i].aitype!=playercontrolled){
+ player[i].velocity.y=7;
+ player[i].crouchtogglekeydown=1;
+ }
+ else player[i].velocity.y=5;
+
+ if(mousejump&&i==0&&debugmode){
+ if(!player[i].isLanding())player[i].tempdeltav=deltav;
+ if(player[i].tempdeltav<0)player[i].velocity.y-=(float)(player[i].tempdeltav)/multiplier/1000;
+ }
+
+ player[i].coords.y+=.2;
+ player[i].jumppower-=1;
+
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=player[i].coords.x;
+ gLoc[1]=player[i].coords.y;
+ gLoc[2]=player[i].coords.z;
+ vel[0]=player[i].velocity.x;
+ vel[1]=player[i].velocity.y;
+ vel[2]=player[i].velocity.z;
+
+ if(i==0){
+ PlaySoundEx( whooshsound, samp[whooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshsound], 128);
+ FSOUND_SetPaused(channels[whooshsound], FALSE);
+ }
+
+ PlaySoundEx( jumpsound, samp[jumpsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[jumpsound], gLoc, vel);
+ FSOUND_SetVolume(channels[jumpsound], 128);
+ FSOUND_SetPaused(channels[jumpsound], FALSE);
+ }
+ if((player[i].isIdle())&&player[i].jumppower>1){
+ player[i].targetanimation=player[i].getLanding();
+ player[i].landhard=0;
+ player[i].target=0;
+ player[i].targetframe=2;
+ player[i].jumpstart=1;
+ player[i].tempdeltav=deltav;
+ }
+ if(player[i].targetanimation==jumpupanim&&(((!floatjump&&!editorenabled)||!debugmode)||player[i].aitype!=playercontrolled)){
+ if(player[i].jumppower>multiplier*6){
+ player[i].velocity.y+=multiplier*6;
+ player[i].jumppower-=multiplier*6;
+ }
+ if(player[i].jumppower<=multiplier*6){
+ player[i].velocity.y+=player[i].jumppower;
+ player[i].jumppower=0;
+ }
+ }
+ if(((floatjump||editorenabled)&&debugmode)&&i==0)player[i].velocity.y+=multiplier*30;
+ }
+
+ if(!movekey){
+ if(player[i].isRun()||player[i].targetanimation==walkanim){
+ player[i].targetanimation=player[i].getStop();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].targetanimation==sneakanim){
+ player[i].targetanimation=player[i].getCrouch();
+ if(player[i].currentanimation==sneakanim)player[i].target=0;
+ player[i].targetframe=0;
+ }
+ }
+ if(player[i].targetanimation==walkanim&&(player[i].aitype==attacktypecutoff||player[i].aitype==searchtype||(player[i].aitype==passivetype&&player[i].numwaypoints<=1))){
+ player[i].targetanimation=player[i].getStop();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ if(player[i].isRun()&&(player[i].aitype==passivetype)){
+ player[i].targetanimation=player[i].getStop();
+ player[i].target=0;
+ player[i].targetframe=0;
+ }
+ }
+ }
+ if(player[i].targetanimation==rollanim)player[i].targetrotation=oldtargetrotation;
+ }
+
+ //Rotation
+ for(k=0;k<numplayers;k++){
+ if(abs(player[k].rotation-player[k].targetrotation)>180){
+ if(player[k].rotation>player[k].targetrotation)player[k].rotation-=360;
+ else player[k].rotation+=360;
+ }
+
+ if(abs(player[k].rotation-player[k].targetrotation)>90&&(player[k].isRun()||player[k].targetanimation==walkanim)){
+ player[k].targetanimation=player[k].getStop();
+ player[k].targetframe=0;
+ player[k].target=0;
+ }
+
+ if(player[k].targetanimation==backhandspringanim||player[k].targetanimation==dodgebackanim){
+ player[k].targettilt=0;
+ }
+ if(player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=backhandspringanim&&player[k].targetanimation!=jumpdownanim&&!player[k].isFlip()){
+ player[k].targettilt=0;
+ if(player[k].jumppower<0&&!player[k].jumpkeydown)player[k].jumppower=0;
+ player[k].jumppower+=multiplier*7;
+ if(player[k].isCrouch())player[k].jumppower+=multiplier*7;
+ //*(1-(player[k].damage/player[k].damagetolerance))
+ if(player[k].jumppower>5)player[k].jumppower=5;
+ }
+
+ if(player[k].isRun()){
+ player[k].targettilt=(player[k].rotation-player[k].targetrotation)/4;
+ }
+
+ if(abs(player[k].tilt-player[k].targettilt)<multiplier*150)player[k].tilt=player[k].targettilt;
+ else if(player[k].tilt>player[k].targettilt){
+ player[k].tilt-=multiplier*150;
+ }
+ else if(player[k].tilt<player[k].targettilt){
+ player[k].tilt+=multiplier*150;
+ }
+
+ player[k].grabdelay-=multiplier;
+ }
+
+ for(k=0;k<numplayers;k++){
+ player[k].DoAnimations();
+ player[k].whichpatchx=player[k].coords.x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ player[k].whichpatchz=player[k].coords.z/(terrain.size/subdivision*terrain.scale*terraindetail);
+ }
+
+ objects.DoStuff();
+ /*
+ player[0].righthandmorphstart=0;
+ player[0].righthandmorphend=1;
+ player[0].lefthandmorphstart=0;
+ player[0].lefthandmorphend=1;
+ player[0].headmorphstart=0;
+ player[0].headmorphend=2;*/
+
+ /*
+ if(IsKeyDown( theKeyMap, MAC_P_KEY )){
+ if(player[0].righthandmorphend!=1)player[0].righthandmorphness=0;
+ player[0].righthandmorphend=1;
+ player[0].targetrighthandmorphness=1;
+
+ if(player[0].lefthandmorphend!=0)player[0].lefthandmorphness=0;
+ player[0].lefthandmorphend=0;
+ player[0].targetlefthandmorphness=1;
+
+ if(player[0].headmorphend!=2)player[0].headmorphness=0;
+ player[0].headmorphend=2;
+ player[0].targetheadmorphness=1;
+ }
+ if(IsKeyDown( theKeyMap, MAC_L_KEY )){
+ if(player[0].righthandmorphend!=0)player[0].righthandmorphness=0;
+ player[0].righthandmorphend=0;
+ player[0].targetrighthandmorphness=1;
+
+ if(player[0].lefthandmorphend!=1)player[0].lefthandmorphness=0;
+ player[0].lefthandmorphend=1;
+ player[0].targetlefthandmorphness=1;
+
+ if(player[0].headmorphend!=0)player[0].headmorphness=0;
+ player[0].headmorphend=0;
+ player[0].targetheadmorphness=1;
+ }
+ */
+ if(numenvsounds!=0)
+ for(j=numenvsounds-1;j>=0;j--){
+ envsoundlife[j]-=multiplier;
+ if(envsoundlife[j]<0){
+ numenvsounds--;
+ envsoundlife[j]=envsoundlife[numenvsounds];
+ envsound[j]=envsound[numenvsounds];
+ }
+ }
+ if(!slomo)FSOUND_SetFrequency(FSOUND_ALL, 22050);
+ if(slomo)FSOUND_SetFrequency(FSOUND_ALL, slomofreq);
+
+ if(tutoriallevel==1){
+ XYZ temp;
+ XYZ temp2;
+ XYZ temp3;
+ XYZ oldtemp;
+ XYZ oldtemp2;
+ temp.x=1011;
+ temp.y=84;
+ temp.z=491;
+ temp2.x=1025;
+ temp2.y=75;
+ temp2.z=447;
+ temp3.x=1038;
+ temp3.y=76;
+ temp3.z=453;
+ oldtemp=temp;
+ oldtemp2=temp2;
+ if(tutorialstage>=51)
+ if(findDistancefast(&temp,&player[0].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[0].coords)<4){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+
+ gameon=0;
+ mainmenu=5;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+ if(tutorialstage<51)
+ if(findDistancefast(&temp,&player[0].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[0].coords)<4){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[0].coords.x;
+ gLoc[1]=player[0].coords.y;
+ gLoc[2]=player[0].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+
+ player[0].coords=(oldtemp+oldtemp2)/2;
+
+ flashr=1;
+ flashg=1;
+ flashb=1;
+ flashamount=1;
+ flashdelay=1;
+ }
+ if(tutorialstage>=14&&tutorialstage<50)
+ if(findDistancefast(&temp,&player[1].coords)>=findDistancefast(&temp,&temp2)-1||findDistancefast(&temp3,&player[1].coords)<4){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[1].coords.x;
+ gLoc[1]=player[1].coords.y;
+ gLoc[2]=player[1].coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+
+ for(int i=0;i<player[1].skeleton.num_joints;i++){
+ if(Random()%2==0){
+ if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
+ if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
+ if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
+ if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
+ sprites.MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
+ }
+ }
+
+ player[1].coords=(oldtemp+oldtemp2)/2;
+ for(int i=0;i<player[1].skeleton.num_joints;i++){
+ player[1].skeleton.joints[i].velocity=0;
+ if(Random()%2==0){
+ if(!player[1].skeleton.free)temp2=(player[1].coords-player[1].oldcoords)/multiplier/2;//velocity/2;
+ if(player[1].skeleton.free)temp2=player[1].skeleton.joints[i].velocity*player[1].scale/2;
+ if(!player[1].skeleton.free)temp=DoRotation(DoRotation(DoRotation(player[1].skeleton.joints[i].position,0,0,player[1].tilt),player[1].tilt2,0,0),0,player[1].rotation,0)*player[1].scale+player[1].coords;
+ if(player[1].skeleton.free)temp=player[1].skeleton.joints[i].position*player[1].scale+player[1].coords;
+ sprites.MakeSprite(breathsprite, temp,temp2, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
+ }
+ }
+ }
+ }
+
+
+ //3d sound
+ static float gLoc[3];
+ gLoc[0]=viewer.x;
+ gLoc[1]=viewer.y;
+ gLoc[2]=viewer.z;
+ static float vel[3];
+ vel[0]=(viewer.x-oldviewer.x)/multiplier;
+ vel[1]=(viewer.y-oldviewer.y)/multiplier;
+ vel[2]=(viewer.z-oldviewer.z)/multiplier;
+
+ //Set orientation with forward and up vectors
+ static XYZ upvector;
+ upvector=0;
+ upvector.z=-1;
+
+ upvector=DoRotation(upvector,-rotation2+90,0,0);
+ upvector=DoRotation(upvector,0,0-rotation,0);
+
+ facing=0;
+ facing.z=-1;
+
+ facing=DoRotation(facing,-rotation2,0,0);
+ facing=DoRotation(facing,0,0-rotation,0);
+
+
+ static float ori[6];
+ ori[0] = -facing.x;
+ ori[1] = facing.y;
+ ori[2] = -facing.z;
+ ori[3] = -upvector.x;
+ ori[4] = upvector.y;
+ ori[5] = -upvector.z;
+
+ FSOUND_3D_Listener_SetAttributes(&gLoc[0], &vel[0], ori[0], ori[1], ori[2], ori[3], ori[4], ori[5]);
+ FSOUND_Update();
+
+ oldviewer=viewer;
+ }
+ }
+
+ if(IsKeyDown(theKeyMap, MAC_F1_KEY)&&!freezetogglekeydown){
+ Screenshot();
+ freezetogglekeydown=1;
+ }
+}
+
+void Game::TickOnce(){
+ //if(!console){
+ if(!mainmenu)
+ if(directing||indialogue==-1){
+ rotation+=deltah*.7;
+ if(!invertmouse)rotation2+=deltav*.7;
+ if(invertmouse)rotation2-=deltav*.7;
+ if(rotation2>90)rotation2=90;
+ if(rotation2<-70)rotation2=-70;
+ }
+ if(mainmenu)rotation+=multiplier*5;
+ if(!mainmenu&&!indemo&&!registered){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+
+ gameon=0;
+ mainmenu=12;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+
+ if(tryquit==1&&!registered&&mainmenu!=12){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+
+ gameon=0;
+ mainmenu=12;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+ //}
+}
+
+void Game::TickOnceAfter(){
+ static XYZ colviewer;
+ static XYZ coltarget;
+ static XYZ target;
+ static XYZ col;
+ static float brotate;
+ static XYZ facing;
+ static int i,j;
+ static float changedelay;
+ static bool alldead;
+ static float unseendelay;
+ static float cameraspeed;
+
+ if(!mainmenu){
+
+ if(environment==snowyenvironment)music1=stream_music1snow;
+ if(environment==grassyenvironment)music1=stream_music1grass;
+ if(environment==desertenvironment)music1=stream_music1desert;
+
+ realthreat=0;
+
+ musictype=music1;
+ for(i=0;i<numplayers;i++){
+ if((player[i].aitype==attacktypecutoff||player[i].aitype==getweapontype||player[i].aitype==gethelptype||player[i].aitype==searchtype)&&!player[i].dead/*&&player[i].surprised<=0*/&&(player[i].targetanimation!=sneakattackedanim&&player[i].targetanimation!=knifesneakattackedanim&&player[i].targetanimation!=swordsneakattackedanim)){
+ musictype=stream_music2;
+ realthreat=1;
+ }
+ }
+ if(player[0].dead)musictype=stream_music3;
+
+
+ if(musictype==stream_music2){
+ unseendelay=1;
+ }
+
+ if(oldmusictype==stream_music2&&musictype!=stream_music2){
+ unseendelay-=multiplier;
+ if(unseendelay>0){
+ musictype=stream_music2;
+ }
+ }
+
+
+ if(loading==2){
+ musictype=stream_music3;
+ musicvolume[2]=512;
+ musicvolume[0]=0;
+ musicvolume[1]=0;
+ musicvolume[3]=0;
+ }
+
+ if(musictoggle){
+ if(musictype!=oldmusictype&&musictype==stream_music2){
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=cameraloc.x;
+ gLoc[1]=cameraloc.y;
+ gLoc[2]=cameraloc.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( alarmsound, samp[alarmsound], NULL, TRUE);
+ FSOUND_SetVolume(channels[alarmsound], 512);
+ FSOUND_SetPaused(channels[alarmsound], FALSE);
+
+ }
+ }
+ musicselected=musictype;
+
+ if(musicselected==music1)musicvolume[0]+=multiplier*450;
+ else musicvolume[0]-=multiplier*450;
+ if(musicselected==stream_music2)musicvolume[1]+=multiplier*450;
+ else musicvolume[1]-=multiplier*450;
+ if(musicselected==stream_music3)musicvolume[2]+=multiplier*450;
+ else musicvolume[2]-=multiplier*450;
+ /*
+ if(musicselected==music1)musicvolume[0]+=multiplier*100;
+ else musicvolume[0]-=multiplier*450;
+ if(musicselected==music2)musicvolume[1]+=multiplier*150;
+ else if(player[0].dead)musicvolume[1]-=multiplier*450;
+ else musicvolume[1]-=multiplier*100;
+ if(musicselected==music3)musicvolume[2]+=multiplier*450;
+ else musicvolume[2]-=multiplier*450;*/
+
+ for(i=0;i<3;i++){
+ if(musicvolume[i]<0)musicvolume[i]=0;
+ if(musicvolume[i]>512)musicvolume[i]=512;
+ }
+
+ if(musicvolume[2]>128&&!loading&&!mainmenu)musicvolume[2]=128;
+
+ if(musictoggle){
+ if(musicvolume[0]>0&&oldmusicvolume[0]<=0){
+ PlayStreamEx( music1, strm[music1], NULL, TRUE);
+ FSOUND_SetPaused(channels[music1], FALSE);
+ }
+ if(musicvolume[1]>0&&oldmusicvolume[1]<=0){
+ PlayStreamEx( stream_music2, strm[stream_music2], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music2], FALSE);
+ }
+ if(musicvolume[2]>0&&oldmusicvolume[2]<=0){
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ }
+ }
+
+ if(!musictoggle){
+ FSOUND_SetPaused(channels[music1], TRUE);
+ FSOUND_SetPaused(channels[stream_music2], TRUE);
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+
+ for(i=0;i<4;i++){
+ oldmusicvolume[i]=0;
+ musicvolume[i]=0;
+ }
+ }
+
+ if(musictoggle){
+ if(musicvolume[0]<=0&&oldmusicvolume[0]>0){
+ FSOUND_SetPaused(channels[music1], TRUE);
+ }
+ if(musicvolume[1]<=0&&oldmusicvolume[1]>0){
+ FSOUND_SetPaused(channels[stream_music2], TRUE);
+ }
+ if(musicvolume[2]<=0&&oldmusicvolume[2]>0){
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+ }
+
+ if(musicvolume[0]!=oldmusicvolume[0]){
+ FSOUND_SetVolume(channels[music1], musicvolume[0]);
+ }
+ if(musicvolume[1]!=oldmusicvolume[1]){
+ FSOUND_SetVolume(channels[stream_music2], musicvolume[1]);
+ }
+ if(musicvolume[2]!=oldmusicvolume[2]){
+ FSOUND_SetVolume(channels[stream_music3], musicvolume[2]);
+ }
+
+ for(i=0;i<3;i++){
+ oldmusicvolume[i]=musicvolume[i];
+ }
+ }
+
+ killhotspot=2;
+ if(numhotspots)
+ for(i=0;i<numhotspots;i++){
+ if(hotspottype[i]>10&&hotspottype[i]<20){
+ if(player[hotspottype[i]-10].dead==0){
+ killhotspot=0;
+ }
+ else if(killhotspot==2)
+ killhotspot=1;
+ }
+ }
+ if(killhotspot==2)killhotspot=0;
+
+
+ winhotspot=0;
+ if(numhotspots)
+ for(i=0;i<numhotspots;i++){
+ if(hotspottype[i]==-1){
+ if(findDistancefast(&player[0].coords,&hotspot[i])<hotspotsize[i])
+ winhotspot=1;
+ }
+ }
+
+ int numalarmed=0;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ if(!player[i].dead&&player[i].aitype==attacktypecutoff&&player[i].surprised<=0)numalarmed++;
+ }
+ if(numalarmed>maxalarmed)maxalarmed=numalarmed;
+
+ if(changedelay<=0&&!loading&&!editorenabled&&gameon&&!tutoriallevel&&changedelay!=-999&&!won){
+ if(player[0].dead&&changedelay<=0){
+ changedelay=1;
+ targetlevel=whichlevel;
+ }
+ alldead=1;
+ if(numplayers>1)
+ for(i=1;i<numplayers;i++){
+ if(!player[i].dead&&player[i].howactive<typedead1)alldead=0;
+ }
+
+
+ if(alldead&&!player[0].dead&&maptype==mapkilleveryone){
+ changedelay=1;
+ targetlevel=whichlevel+1;
+ if(targetlevel>numchallengelevels-1)targetlevel=0;
+ }
+ if(winhotspot||windialogue){
+ changedelay=0.1;
+ targetlevel=whichlevel+1;
+ if(targetlevel>numchallengelevels-1)targetlevel=0;
+ }
+
+
+ if(killhotspot){
+ changedelay=1;
+ targetlevel=whichlevel+1;
+ if(targetlevel>numchallengelevels-1)targetlevel=0;
+ }
+
+ if(changedelay>0&&!player[0].dead&&!won){
+ //high scores, awards, win
+ if(campaign){
+ won=1;
+ accountcampaignchoices[accountactive][accountcampaignchoicesmade[accountactive]]=whichchoice;
+ accountcampaignchoicesmade[accountactive]++;
+ accountcampaignscore[accountactive]+=bonustotal;
+ scoreadded=1;
+ accountcampaigntime[accountactive]+=leveltime;
+ if(accountcampaignscore[accountactive]>accountcampaignhighscore[accountactive])accountcampaignhighscore[accountactive]=accountcampaignscore[accountactive];
+
+ //if(accountprogress[accountactive]<whichlevel+1)accountprogress[accountactive]=whichlevel+1;
+ }
+ else
+ {
+ won=1;
+ if(!debugmode){
+ if(bonustotal-startbonustotal>accounthighscore[accountactive][whichlevel])accounthighscore[accountactive][whichlevel]=bonustotal-startbonustotal;
+ if(accountfasttime[accountactive][whichlevel]==0||leveltime<accountfasttime[accountactive][whichlevel])accountfasttime[accountactive][whichlevel]=leveltime;
+ }
+ if(accountprogress[accountactive]<whichlevel+1)accountprogress[accountactive]=whichlevel+1;
+
+ }
+ }
+ }
+
+ if(!winfreeze){
+
+ if(leveltime<1){
+ loading=0;
+ changedelay=.1;
+ alldead=0;
+ winhotspot=0;
+ killhotspot=0;
+ }
+
+ if(!editorenabled&&gameon&&!mainmenu){
+ if(changedelay!=-999)changedelay-=multiplier/7;
+ if(player[0].dead)targetlevel=whichlevel;
+ if(loading==2&&!campaign){
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ loadtime=0;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ if(!player[0].dead&&targetlevel!=whichlevel){
+ startbonustotal=bonustotal;
+ }
+ if(!player[0].dead)Loadlevel(targetlevel);
+ if(player[0].dead)Loadlevel(whichlevel);
+
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ loading=3;
+ }
+ if(loading==2&&targetlevel==whichlevel){
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ loadtime=0;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ for(i=0;i<255;i++){
+ mapname[i]='\0';
+ }
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+ strcat(mapname,campaignmapname[levelorder[accountcampaignchoicesmade[accountactive]]]);//[campaignchoicewhich[whichchoice]]);
+ Loadlevel(mapname);
+
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ loading=3;
+ }
+ if(changedelay<=-999&&whichlevel!=-2&&!loading&&(player[0].dead||(alldead&&maptype==mapkilleveryone)||(winhotspot)||(killhotspot))&&!winfreeze)loading=1;
+ if((player[0].dead||(alldead&&maptype==mapkilleveryone)||(winhotspot)||(windialogue)||(killhotspot))&&changedelay<=0){
+ if(accountprogress[accountactive]>3&&!registered){
+ FSOUND_SetFrequency(FSOUND_ALL, 0.001);
+ PlayStreamEx( stream_music3, strm[stream_music3], NULL, TRUE);
+ FSOUND_SetPaused(channels[stream_music3], FALSE);
+ FSOUND_SetVolume(channels[stream_music3], 256);
+
+ gameon=0;
+ mainmenu=12;
+ accountprogress[accountactive]=3;
+
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 9999.0f, 99999.0f);
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[fireendsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+ else{
+ if(whichlevel!=-2&&!loading&&!player[0].dead){
+ winfreeze=1;
+ changedelay=-999;
+ }
+ if(player[0].dead)loading=1;
+ }
+ }
+ }
+
+ if(campaign)
+ if(mainmenu==0&&winfreeze&&(campaignchoosenext[campaignchoicewhich[whichchoice]])==1){
+ if(campaignnumnext[campaignchoicewhich[whichchoice]]==0){
+ endgame=1;
+ }
+ }
+ else if(mainmenu==0&&winfreeze){
+ if(campaignchoosenext[campaignchoicewhich[whichchoice]]==2)
+ stealthloading=1;
+ else stealthloading=0;
+
+ if(!stealthloading){
+ float gLoc[3]={0,0,0};
+ float vel[3]={0,0,0};
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 9999.0f, 99999.0f);
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ FSOUND_Sample_SetMinMaxDistance(samp[firestartsound], 8.0f, 2000.0f);
+
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashamount=1;
+ flashdelay=1;
+ }
+
+ startbonustotal=0;
+
+ // ifstream ipstream(":Data:Campaigns:main.txt");
+ ifstream ipstream("./Data/Campaigns/main.txt");
+ //campaignnumlevels=0;
+ //accountcampaignchoicesmade[accountactive]=0;
+ ipstream.ignore(256,':');
+ ipstream >> campaignnumlevels;
+ for(i=0;i<campaignnumlevels;i++){
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,':');
+ ipstream.ignore(256,' ');
+ ipstream >> campaignmapname[i];
+ ipstream.ignore(256,':');
+ ipstream >> campaigndescription[i];
+ for(j=0;j<256;j++){
+ if(campaigndescription[i][j]=='_')campaigndescription[i][j]=' ';
+ }
+ ipstream.ignore(256,':');
+ ipstream >> campaignchoosenext[i];
+ ipstream.ignore(256,':');
+ ipstream >> campaignnumnext[i];
+ if(campaignnumnext[i])
+ for(j=0;j<campaignnumnext[i];j++){
+ ipstream.ignore(256,':');
+ ipstream >> campaignnextlevel[i][j];
+ campaignnextlevel[i][j]-=1;
+ }
+ ipstream.ignore(256,':');
+ ipstream >> campaignlocationx[i];
+ ipstream.ignore(256,':');
+ ipstream >> campaignlocationy[i];
+ }
+ ipstream.close();
+
+ for(i=0;i<campaignnumlevels;i++){
+ levelvisible[i]=0;
+ levelhighlight[i]=0;
+ }
+
+
+ for(i=0;i<campaignnumlevels;i++){
+ levelvisible[i]=0;
+ levelhighlight[i]=0;
+ }
+
+ levelorder[0]=0;
+ levelvisible[0]=1;
+ if(accountcampaignchoicesmade[accountactive])
+ for(i=0;i<accountcampaignchoicesmade[accountactive];i++){
+ levelorder[i+1]=campaignnextlevel[levelorder[i]][accountcampaignchoices[accountactive][i]];
+ levelvisible[levelorder[i+1]]=1;
+ }
+ int whichlevelstart;
+ whichlevelstart=accountcampaignchoicesmade[accountactive]-1;
+ if(whichlevelstart<0){
+ campaignchoicenum=1;
+ campaignchoicewhich[0]=0;
+ }
+ else
+ {
+ campaignchoicenum=campaignnumnext[levelorder[whichlevelstart]];
+ if(campaignchoicenum)
+ for(i=0;i<campaignchoicenum;i++){
+ campaignchoicewhich[i]=campaignnextlevel[levelorder[whichlevelstart]][i];
+ levelvisible[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ levelhighlight[campaignnextlevel[levelorder[whichlevelstart]][i]]=1;
+ }
+ }
+
+ loading=2;
+ loadtime=0;
+ targetlevel=7;
+ //if(firstload)TickOnceAfter();
+ if(!firstload)LoadStuff();
+ //else {
+ for(i=0;i<255;i++){
+ mapname[i]='\0';
+ }
+ mapname[0]=':';
+ mapname[1]='D';
+ mapname[2]='a';
+ mapname[3]='t';
+ mapname[4]='a';
+ mapname[5]=':';
+ mapname[6]='M';
+ mapname[7]='a';
+ mapname[8]='p';
+ mapname[9]='s';
+ mapname[10]=':';
+
+ //accountcampaignchoices[accountactive][accountcampaignchoicesmade[accountactive]]=whichchoice;
+ //accountcampaignchoicesmade[accountactive]++;
+
+
+ strcat(mapname,campaignmapname[campaignchoicewhich[0]]);
+ whichchoice=0;
+ visibleloading=1;
+ stillloading=1;
+ Loadlevel(mapname);
+ campaign=1;
+ mainmenu=0;
+ gameon=1;
+ FSOUND_SetPaused(channels[stream_music3], TRUE);
+
+ stealthloading=0;
+ }
+
+ if(loading==3)loading=0;
+
+ }
+
+ oldmusictype=musictype;
+ }
+
+ facing=0;
+ facing.z=-1;
+
+ facing=DoRotation(facing,-rotation2,0,0);
+ facing=DoRotation(facing,0,0-rotation,0);
+ viewerfacing=facing;
+
+ brotate=0;
+ if(!cameramode){
+ if((animation[player[0].targetanimation].attack!=3&&animation[player[0].currentanimation].attack!=3)||player[0].skeleton.free)target=player[0].coords+player[0].currentoffset*(1-player[0].target)*player[0].scale+player[0].targetoffset*player[0].target*player[0].scale-player[0].facing*.05;
+ else target=player[0].oldcoords+player[0].currentoffset*(1-player[0].target)*player[0].scale+player[0].targetoffset*player[0].target*player[0].scale-player[0].facing*.05;
+ target.y+=.1;
+ if(player[0].skeleton.free){
+ for(i=0;i<player[0].skeleton.num_joints;i++){
+ if(player[0].skeleton.joints[i].position.y*player[0].scale+player[0].coords.y>target.y)
+ target.y=player[0].skeleton.joints[i].position.y*player[0].scale+player[0].coords.y;
+ }
+ target.y+=.1;
+ }
+ if(player[0].skeleton.free!=2&&!autocam){
+ cameraspeed=20;
+ if(findLengthfast(&player[0].velocity)>400){
+ cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
+ }
+ if(player[0].skeleton.free==0&&player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim)target.y+=1.4;
+ coltarget=target-cameraloc;
+ if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
+ else {
+ Normalise(&coltarget);
+ if(player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim&&player[0].currentanimation!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
+ else cameraloc=cameraloc+coltarget*multiplier*8;
+ }
+ if(editorenabled)cameraloc=target;
+ cameradist+=multiplier*5;
+ if(cameradist>2.3)cameradist=2.3;
+ viewer=cameraloc-facing*cameradist;
+ colviewer=viewer;
+ coltarget=cameraloc;
+ objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
+ if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
+ for(j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
+ i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
+ colviewer=viewer;
+ coltarget=cameraloc;
+ if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.rotation[i])!=-1)viewer=col;
+ }
+ if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
+ for(j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
+ i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
+ colviewer=viewer;
+ if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.rotation[i])!=-1){
+ viewer=colviewer;
+ }
+ }
+ cameradist=findDistance(&viewer,&target);
+ if(viewer.y<terrain.getHeight(viewer.x,viewer.z)+.6){
+ viewer.y=terrain.getHeight(viewer.x,viewer.z)+.6;
+ }
+ if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
+ cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
+ }
+ }
+ if(player[0].skeleton.free!=2&&autocam){
+ cameraspeed=20;
+ if(findLengthfast(&player[0].velocity)>400){
+ cameraspeed=20+(findLength(&player[0].velocity)-20)*.96;
+ }
+ if(player[0].skeleton.free==0&&player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim)target.y+=1.4;
+ cameradist+=multiplier*5;
+ if(cameradist>3.3)cameradist=3.3;
+ coltarget=target-cameraloc;
+ if(findLengthfast(&coltarget)<multiplier*multiplier*400)cameraloc=target;
+ else if(findLengthfast(&coltarget)>1)
+ {
+ Normalise(&coltarget);
+ if(player[0].targetanimation!=hanganim&&player[0].targetanimation!=climbanim&&player[0].currentanimation!=climbanim&&player[0].currentoffset.x==0)cameraloc=cameraloc+coltarget*multiplier*cameraspeed;
+ else cameraloc=cameraloc+coltarget*multiplier*8;
+ }
+ if(editorenabled)cameraloc=target;
+ viewer=cameraloc;
+ colviewer=viewer;
+ coltarget=cameraloc;
+ objects.SphereCheckPossible(&colviewer, findDistance(&colviewer,&coltarget));
+ if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
+ for(j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
+ i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
+ colviewer=viewer;
+ coltarget=cameraloc;
+ if(objects.model[i].LineCheckPossible(&colviewer,&coltarget,&col,&objects.position[i],&objects.rotation[i])!=-1)viewer=col;
+ }
+ if(terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz])
+ for(j=0;j<terrain.patchobjectnum[player[0].whichpatchx][player[0].whichpatchz];j++){
+ i=terrain.patchobjects[player[0].whichpatchx][player[0].whichpatchz][j];
+ colviewer=viewer;
+ if(objects.model[i].SphereCheck(&colviewer,.15,&col,&objects.position[i],&objects.rotation[i])!=-1){
+ viewer=colviewer;
+ }
+ }
+ cameradist=findDistance(&viewer,&target);
+ if(viewer.y<terrain.getHeight(viewer.x,viewer.z)+.6){
+ viewer.y=terrain.getHeight(viewer.x,viewer.z)+.6;
+ }
+ if(cameraloc.y<terrain.getHeight(cameraloc.x,cameraloc.z)){
+ cameraloc.y=terrain.getHeight(cameraloc.x,cameraloc.z);
+ }
+ }
+ if(camerashake>.8)camerashake=.8;
+ //if(woozy>10)woozy=10;
+ //woozy+=multiplier;
+ woozy+=multiplier;
+ if(player[0].dead)camerashake=0;
+ if(player[0].dead)woozy=0;
+ camerashake-=multiplier*2;
+ blackout-=multiplier*2;
+ //if(player[0].isCrouch())woozy-=multiplier*8;
+ if(camerashake<0)camerashake=0;
+ if(blackout<0)blackout=0;
+ //if(woozy<0)woozy=0;
+ if(camerashake){
+ viewer.x+=(float)(Random()%100)*.0005*camerashake;
+ viewer.y+=(float)(Random()%100)*.0005*camerashake;
+ viewer.z+=(float)(Random()%100)*.0005*camerashake;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+#include "gl.h"
+#include "Quaternions.h"
+#include "Lights.h"
+#include "Skeleton.h"
+#include "fmod.h"
+#include "Terrain.h"
+#include "Sprites.h"
+//#include <agl.h>
+#include "Frustum.h"
+#include "Objects.h"
+#include "Weapons.h"
+#include "Person.h"
+#include "TGALoader.h"
+
+#include "Constants.h"
+
+bool visibleloading = 0;
+FSOUND_SAMPLE *samp[100] = {0};
+FSOUND_STREAM * strm[20] = {0};
+int channels[100] = {0};
+
+float volume = 0;bool buttons[3] = {0};
+bool oldbuttons[3] = {0};
+bool ismotionblur = 0;
+float usermousesensitivity = 0;
+bool floatjump = 0;
+bool cellophane = 0;
+bool autoslomo = 0;
+bool decals = 0;
+bool invertmouse = 0;
+bool texttoggle = 0;
+float blurness = 0;
+float targetblurness = 0;
+float windvar = 0;
+float precipdelay = 0;
+float gamespeed = 0;
+float oldgamespeed = 0;
+float tintr = 0,tintg = 0,tintb = 0;
+int difficulty = 0;
+float multiplier = 0;
+float realmultiplier = 0;
+float screenwidth = 0,screenheight = 0;
+float viewdistance = 0;
+XYZ viewer;
+XYZ viewerfacing;
+XYZ lightlocation;
+float fadestart = 0;
+int environment = 0;
+float texscale = 0;
+float gravity = 0;
+Light light;
+Animation animation[animation_count];
+Skeleton testskeleton;
+int numsounds = 0;
+Terrain terrain;
+Sprites sprites;
+float sps = 0;
+#ifdef WIN32
+HDC hDC;
+#else
+AGLContext gaglContext;
+#endif
+int kTextureSize = 0;
+int detail = 0;
+FRUSTUM frustum;
+float texdetail = 0;
+float realtexdetail = 0;
+float terraindetail = 0;
+float playerdist = 0;
+Objects objects;
+int slomo = 0;
+float slomodelay = 0;
+GLubyte bloodText[512*512*3] = {0};
+GLubyte wolfbloodText[512*512*3] = {0};
+float colors[3] = {0};
+int bloodtoggle = 0;
+bool osx = 0;
+float camerashake = 0;
+float woozy = 0;
+float blackout = 0;
+bool foliage = 0;
+bool musictoggle = 0;
+bool trilinear;
+Weapons weapons;
+bool damageeffects = 0;
+//apvector<Person> player(maxplayers);
+Person player[maxplayers];
+int numplayers = 0;
+bool ambientsound = 0;
+bool mousejump = 0;
+bool freeze = 0;
+bool winfreeze = 0;
+float flashamount = 0,flashr = 0,flashg = 0,flashb = 0;
+int flashdelay = 0;
+bool vblsync = 0;
+float motionbluramount = 0;
+bool keyboardfrozen = 0;
+int newnetmessages = 0;
+char netmessages[256] = {0};
+char mapname[256] = {0};
+bool loadingstuff = 0;
+bool stillloading = 0;
+bool showpoints = 0;
+bool alwaysblur = 0;
+bool immediate = 0;
+bool velocityblur = 0;
+int test = 0;
+XYZ windvector;
+short vRefNum = 0;
+long dirID = 0;
+int mainmenu = 0;
+int oldmainmenu = 0;
+GLubyte texturearray[512*512*3] = {0};
+int loadscreencolor = 0;
+int whichjointstartarray[26] = {0};
+int whichjointendarray[26] = {0};
+int kBitsPerPixel = 0;
+
+int numhotspots = 0;
+XYZ hotspot[40];
+int hotspottype[40] = {0};
+float hotspotsize[40] = {0};
+char hotspottext[40][256] = {0};
+int currenthotspot = 0;
+int winhotspot = 0;
+int windialogue = 0;
+int killhotspot = 0;
+
+float menupulse = 0;
+
+int numdialogues = 0;
+int numdialogueboxes[max_dialogues] = {0};
+int dialoguetype[max_dialogues] = {0};
+int dialogueboxlocation[max_dialogues][max_dialoguelength] = {0};
+float dialogueboxcolor[max_dialogues][max_dialoguelength][3] = {0};
+int dialogueboxsound[max_dialogues][max_dialoguelength] = {0};
+char dialoguetext[max_dialogues][max_dialoguelength][128] = {0};
+char dialoguename[max_dialogues][max_dialoguelength][64] = {0};
+XYZ dialoguecamera[max_dialogues][max_dialoguelength] = {0};
+XYZ participantlocation[max_dialogues][10] = {0};
+int participantfocus[max_dialogues][max_dialoguelength] = {0};
+int participantaction[max_dialogues][max_dialoguelength] = {0};
+float participantrotation[max_dialogues][10] = {0};
+XYZ participantfacing[max_dialogues][max_dialoguelength][10] = {0};
+float dialoguecamerarotation[max_dialogues][max_dialoguelength] = {0};
+float dialoguecamerarotation2[max_dialogues][max_dialoguelength] = {0};
+int indialogue = 0;
+int whichdialogue = 0;
+int directing = 0;
+float dialoguetime = 0;
+int dialoguegonethrough[20] = {0};
+
+float smoketex = 0;
+
+float slomospeed = 0;
+float slomofreq = 0;
+
+int tutoriallevel = 0;
+int tutorialstage = 0;
+float tutorialstagetime = 0;
+float tutorialmaxtime = 0;
+float tutorialsuccess = 0;
+
+bool againbonus = 0;
+
+float damagedealt = 0;
+float damagetaken = 0;
+
+int maptype = 0;
+
+int editoractive = 0;
+int editorpathtype = 0;
+
+bool reversaltrain = 0;
+bool cananger = 0;
+bool canattack = 0;
+
+bool skyboxtexture = 0;
+float skyboxr = 0;
+float skyboxg = 0;
+float skyboxb = 0;
+float skyboxlightr = 0;
+float skyboxlightg = 0;
+float skyboxlightb = 0;
+
+float bonusnum[100] = {0};
+
+int hostile = 0;
+float hostiletime = 0;
+
+XYZ envsound[30] = {0};
+float envsoundvol[30] = {0};
+float envsoundlife[30] = {0};
+int numenvsounds;
+
+
+bool tilt2weird = 0;
+bool tiltweird = 0;
+bool midweird = 0;
+bool proportionweird = 0;
+bool vertexweird[6] = {0};
+TGAImageRec texture;
+bool debugmode = 0;
+
+int oldbonus = 0;
+int bonus = 0;
+float bonusvalue = 0;
+float bonustotal = 0;
+float startbonustotal = 0;
+float bonustime = 0;
+
+int numaccounts = 0;
+int accountactive = 0;
+int accountdifficulty[10] = {0};
+int accountprogress[10] = {0};
+float accountpoints[10] = {0};
+float accounthighscore[10][50] = {0};
+float accountfasttime[10][50] = {0};
+bool accountunlocked[10][60] = {0};
+char accountname[10][256] = {0};
+float accountcampaignhighscore[10] = {0};
+float accountcampaignfasttime[10] = {0};
+float accountcampaignscore[10] = {0};
+float accountcampaigntime[10] = {0};
+int accountcampaignchoicesmade[10] = {0};int accountcampaignchoices[10][5000] = {0};
+bool won = 0;
+
+
+bool campaign = 0;
+
+int numfalls = 0;
+int numflipfail = 0;
+int numseen = 0;
+int numresponded = 0;
+int numstaffattack = 0;
+int numswordattack = 0;
+int numknifeattack = 0;
+int numunarmedattack = 0;
+int numescaped = 0;
+int numflipped = 0;
+int numwallflipped = 0;
+int numthrowkill = 0;
+int numafterkill = 0;
+int numreversals = 0;
+int numattacks = 0;
+int maxalarmed = 0;
+
+bool gamestarted = 0;
+
+//TextureList textures;
--- /dev/null
+/**> HEADER FILES <**/
+#include "Lights.h"
+
+void SetUpLight(Light* whichsource, int whichlight){
+ static float qattenuation[]={0.0002f};
+ static float cattenuation[]={1.5f};
+ static float lattenuation[]={0.5f};
+ static float zattenuation[]={0.0f};
+
+ //Initialize lights
+
+ if(whichlight==0){
+ GLfloat LightAmbient[]= { whichsource->ambient[0], whichsource->ambient[1], whichsource->ambient[2], 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 0.0f };
+
+ //glLightfv(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT0);
+ }
+
+ if(whichlight==1){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT1);
+ }
+
+ if(whichlight==2){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT2, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT2);
+ }
+
+ if(whichlight==3){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT3, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT3, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT3, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT3, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT3);
+ }
+
+ if(whichlight==4){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT4, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT4, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT4, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT4, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT4);
+ }
+
+ if(whichlight==5){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT5, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT5, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT5, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT5, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT5);
+ }
+
+ if(whichlight==6){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT6, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT6, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT6, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT6, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT6);
+ }
+
+ if(whichlight==7){
+ GLfloat LightAmbient[]= { 0, 0, 0, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT7, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT7, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT7, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT7, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT7);
+ }
+}
+
+void SetUpMainLight(Light* whichsource, int whichlight, float ambientr, float ambientg, float ambientb){
+ static float qattenuation[]={0.0f};
+
+ //Initialize lights
+
+ if(whichlight==0){
+ GLfloat LightAmbient[]= { ambientr, ambientg, ambientb, 1.0f};
+ GLfloat LightDiffuse[]= { whichsource->color[0], whichsource->color[1], whichsource->color[2], 1.0f };
+ GLfloat LightPosition[]= { whichsource->location.x, whichsource->location.y, whichsource->location.z, 1.0f };
+
+ glLightfv(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, qattenuation);
+ glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
+ glEnable(GL_LIGHT0);
+ }
+}
\ No newline at end of file
--- /dev/null
+#ifndef _LIGHTS_H_
+#define _LIGHTS_H_
+
+
+/**> HEADER FILES <**/
+#include "gl.h"
+#include "Quaternions.h"
+
+class Light{
+public:
+ GLint type;
+ GLfloat color[3];
+ GLfloat ambient[3];
+ int attach;
+ XYZ location;
+};
+
+void SetUpMainLight(Light* whichsource, int whichlight, float ambientr, float ambientg, float ambientb);
+void SetUpLight(Light* whichsource, int whichlight);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999-2002 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ *
+ * Modified: $Date: 2002/04/27 20:52:48 $
+ * Revision: $Id: LinkedList.h,v 1.3 2002/04/27 20:52:48 lane Exp $
+ */
+
+
+/*
+ File: LinkedList.h
+
+ Contains:
+
+*/
+
+#ifndef __LINKEDLIST__
+#define __LINKEDLIST__
+
+
+//we cant just use "macintosh_build" - the mac macho_build is designated as "posix_build" but may
+//include open transport in some cases
+#ifndef __OPENTRANSPORT__
+//#if (!macintosh_build)
+
+#include <stddef.h> //for OTGetLinkObject replacement
+
+#include "OPUtils.h" //for true/false
+
+#if (windows_build)
+
+// ECF 010928 win32 syncronization routines for safe critical sections. We can't simply use TryEnterCriticalSection()
+// to return a true/false value because it's not available in win95 and 98
+class OSCriticalSection
+{
+ public:
+ NMBoolean locked;
+ OSCriticalSection() {locked = false; InitializeCriticalSection(&theCriticalSection);}
+ ~OSCriticalSection() {DeleteCriticalSection(&theCriticalSection);}
+ NMBoolean acquire() { if (locked == true) return false; //dont have to wait in this case
+ EnterCriticalSection(&theCriticalSection);
+ if (locked) {LeaveCriticalSection(&theCriticalSection); return false;}
+ else {locked = true; LeaveCriticalSection(&theCriticalSection); return true;}}
+ void release() { EnterCriticalSection(&theCriticalSection);
+ locked = false; LeaveCriticalSection(&theCriticalSection);}
+
+ CRITICAL_SECTION theCriticalSection;
+};
+#endif //windows_build
+
+#if (posix_build)
+#include <pthread.h>
+class OSCriticalSection
+{
+ public:
+ OSCriticalSection() {pthread_mutex_init(&theMutex,NULL);}
+ ~OSCriticalSection() {pthread_mutex_destroy(&theMutex);}
+ NMBoolean acquire() { int error = pthread_mutex_trylock(&theMutex);
+ if (error) return false; else return true;}
+ void release() { pthread_mutex_unlock(&theMutex);}
+
+ pthread_mutex_t theMutex;
+};
+
+#endif //(posix_build)
+
+/* -------------------------------------------------------------------------
+ ** OTLIFO
+ **
+ ** These are functions to implement a LIFO list that is interrupt-safe.
+ ** The only function which is not is OTReverseList. Normally, you create
+ ** a LIFO list, populate it at interrupt time, and then use OTLIFOStealList
+ ** to atomically remove the list, and OTReverseList to flip the list so that
+ ** it is a FIFO list, which tends to be more useful.
+ ------------------------------------------------------------------------- */
+
+ class OTLink;
+ class OTLIFO;
+
+ class OTLink
+ {
+ public:
+ OTLink* fNext;
+ void Init()
+ { fNext = NULL; }
+ };
+
+ class OTLIFO
+ {
+ public:
+ OSCriticalSection theLock;
+ OTLink* fHead;
+
+ void Init()
+ { fHead = NULL; }
+
+ void Enqueue(OTLink* link)
+ {
+ while (true) {if (theLock.acquire()) break;}
+ link->fNext = fHead;
+ fHead = link;
+ theLock.release();
+ }
+
+
+ OTLink* Dequeue()
+ {
+ while (true) {if (theLock.acquire()) break;}
+ OTLink *origHead = fHead;
+ fHead = fHead->fNext;
+ theLock.release();
+ return origHead;
+ }
+
+
+ OTLink* StealList()
+ {
+ while (true) {if (theLock.acquire()) break;}
+ OTLink *origHead = fHead;
+ fHead = NULL;
+ theLock.release();
+ return origHead;
+ }
+
+
+ NMBoolean IsEmpty()
+ {
+ return fHead == NULL;
+ }
+ };
+
+/* -------------------------------------------------------------------------
+ ** OTList
+ **
+ ** An OTList is a non-interrupt-safe list, but has more features than the
+ ** OTLIFO list. It is a standard singly-linked list.
+ ------------------------------------------------------------------------- */
+
+ typedef struct OTList OTList;
+
+ typedef NMBoolean (*OTListSearchProcPtr)(const void* ref, OTLink* linkToCheck);
+ //
+ // Remove the last link from the list
+ //
+ extern OTLink* OTRemoveLast(OTList* pList);
+ //
+ // Return the first link from the list
+ //
+ extern OTLink* OTGetFirst(OTList* pList);
+ //
+ // Return the last link from the list
+ //
+ extern OTLink* OTGetLast(OTList* pList);
+ //
+ // Return true if the link is present in the list
+ //
+ extern NMBoolean OTIsInList(OTList* pList, OTLink* link);
+ //
+ // Find a link in the list which matches the search criteria
+ // established by the search proc and the refPtr. This is done
+ // by calling the search proc, passing it the refPtr and each
+ // link in the list, until the search proc returns true.
+ // NULL is returned if the search proc never returned true.
+ //
+ extern OTLink* OTFindLink(OTList* pList, OTListSearchProcPtr proc, const void* refPtr);
+ //
+ // Remove the specified link from the list, returning true if it was found
+ //
+ extern NMBoolean OTRemoveLink(OTList*, OTLink*);
+ //
+ // Similar to OTFindLink, but it also removes it from the list.
+ //
+ extern OTLink* OTFindAndRemoveLink(OTList* pList, OTListSearchProcPtr proc, const void* refPtr);
+ //
+ // Return the "index"th link in the list
+ //
+ extern OTLink* OTGetIndexedLink(OTList* pList, size_t index);
+
+ struct OTList
+ {
+ OTLink* fHead;
+
+ void Init()
+ { fHead = NULL; }
+
+ NMBoolean IsEmpty()
+ { return fHead == NULL; }
+
+ void AddFirst(OTLink* link)
+ {
+ link->fNext = fHead;
+ fHead = link;
+ }
+
+ void AddLast(OTLink* link)
+ {
+ if (fHead == NULL)
+ fHead = link->fNext;
+ else
+ {
+ OTLink *current = fHead;
+
+ while (current->fNext != NULL)
+ current = current->fNext;
+
+ current->fNext = link;
+ }
+
+
+ link->fNext = fHead;
+ fHead = link;
+ }
+
+
+ OTLink* GetFirst()
+ { return OTGetFirst(this); }
+
+ OTLink* GetLast()
+ { return OTGetLast(this); }
+
+ OTLink* RemoveFirst()
+ {
+ OTLink *origHead = fHead;
+ fHead = fHead->fNext;
+ return origHead;
+ }
+
+ OTLink* RemoveLast()
+ { return OTRemoveLast(this); }
+
+ NMBoolean IsInList(OTLink* link)
+ { return OTIsInList(this, link); }
+
+ OTLink* FindLink(OTListSearchProcPtr proc, const void* ref)
+ { return OTFindLink(this, proc, ref); }
+
+ NMBoolean RemoveLink(OTLink* link)
+ { return OTRemoveLink(this, link); }
+
+ OTLink* RemoveLink(OTListSearchProcPtr proc, const void* ref)
+ { return OTFindAndRemoveLink(this, proc, ref); }
+
+ OTLink* GetIndexedLink(size_t index)
+ { return OTGetIndexedLink(this, index); }
+ };
+
+
+//FIXME!! this is a recursive function and will crash and burn on large lists
+static OTLink* OTReverseList(OTLink *headRef)
+{
+ OTLink *first;
+ OTLink *rest;
+
+ if (headRef == NULL) return NULL;
+
+ first = headRef;
+ rest = (OTLink *) first->fNext;
+
+ if (rest == NULL) return headRef;
+
+ rest = OTReverseList(rest);
+
+ first->fNext->fNext = first;
+ first->fNext = NULL;
+
+ return rest;
+}
+
+
+ #define OTGetLinkObject(link, struc, field) \
+ ((struc*)((char*)(link) - offsetof(struc, field)))
+
+#endif //!macintosh_build
+#endif /* __LINKEDLIST__ */
+
--- /dev/null
+// MD5.CC - source code for the C++/object oriented translation and
+// modification of MD5.
+
+// Translation and modification (c) 1995 by Mordechai T. Abzug
+
+// This translation/ modification is provided "as is," without express or
+// implied warranty of any kind.
+
+// The translator/ modifier does not claim (1) that MD5 will do what you think
+// it does; (2) that this translation/ modification is accurate; or (3) that
+// this software is "merchantible." (Language for this disclaimer partially
+// copied from the disclaimer below).
+
+/* based on:
+
+MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+MDDRIVER.C - test driver for MD2, MD4 and MD5
+
+
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+*/
+
+
+
+
+
+
+#include "md5.h"
+
+#include <assert.h>
+//#include <strings.h>
+#include <iostream>
+
+
+
+
+// MD5 simple initialization method
+
+MD5::MD5(){
+
+ init();
+
+}
+
+
+
+
+// MD5 block update operation. Continues an MD5 message-digest
+// operation, processing another message block, and updating the
+// context.
+
+void MD5::update (uint1 *input, uint4 input_length) {
+
+ uint4 input_index, buffer_index;
+ uint4 buffer_space; // how much space is left in buffer
+
+ if (finalized){ // so we can't update!
+ cerr << "MD5::update: Can't update a finalized digest!" << endl;
+ return;
+ }
+
+ // Compute number of bytes mod 64
+ buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
+
+ // Update number of bits
+ if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
+ count[1]++;
+
+ count[1] += ((uint4)input_length >> 29);
+
+
+ buffer_space = 64 - buffer_index; // how much space is left in buffer
+
+ // Transform as many times as possible.
+ if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
+ // fill the rest of the buffer and transform
+ memcpy (buffer + buffer_index, input, buffer_space);
+ transform (buffer);
+
+ // now, transform each 64-byte piece of the input, bypassing the buffer
+ for (input_index = buffer_space; input_index + 63 < input_length;
+ input_index += 64)
+ transform (input+input_index);
+
+ buffer_index = 0; // so we can buffer remaining
+ }
+ else
+ input_index=0; // so we can buffer the whole input
+
+
+ // and here we do the buffering:
+ memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
+}
+
+
+
+// MD5 update for files.
+// Like above, except that it works on files (and uses above as a primitive.)
+
+void MD5::update(FILE *file){
+
+ unsigned char buffer[1024];
+ int len;
+
+ while (len=fread(buffer, 1, 1024, file))
+ update(buffer, len);
+
+ fclose (file);
+
+}
+
+
+
+
+
+
+// MD5 update for istreams.
+// Like update for files; see above.
+
+void MD5::update(istream& stream){
+
+ unsigned char buffer[1024];
+ int len;
+
+ while (stream.good()){
+ stream.read((char *)buffer, (long)1024); // note that return value of read is unusable.
+ len=stream.gcount();
+ update(buffer, len);
+ }
+
+}
+
+
+
+
+
+
+// MD5 update for ifstreams.
+// Like update for files; see above.
+
+void MD5::update(ifstream& stream){
+
+ unsigned char buffer[1024];
+ int len;
+
+ while (stream.good()){
+ stream.read((char *)buffer, (long)1024); // note that return value of read is unusable.
+ len=stream.gcount();
+ update(buffer, len);
+ }
+
+}
+
+
+
+
+
+
+// MD5 finalization. Ends an MD5 message-digest operation, writing the
+// the message digest and zeroizing the context.
+
+
+void MD5::finalize (){
+
+ unsigned char bits[8];
+ unsigned int index, padLen;
+ static uint1 PADDING[64]={
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (finalized){
+ cerr << "MD5::finalize: Already finalized this digest!" << endl;
+ return;
+ }
+
+ // Save number of bits
+ encode (bits, count, 8);
+
+ // Pad out to 56 mod 64.
+ index = (uint4) ((count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ update (PADDING, padLen);
+
+ // Append length (before padding)
+ update (bits, 8);
+
+ // Store state in digest
+ encode (digest, state, 16);
+
+ // Zeroize sensitive information
+ memset (buffer, 0, sizeof(*buffer));
+
+ finalized=1;
+
+}
+
+
+
+
+MD5::MD5(FILE *file){
+
+ init(); // must be called be all constructors
+ update(file);
+ finalize ();
+}
+
+
+
+
+MD5::MD5(istream& stream){
+
+ init(); // must called by all constructors
+ update (stream);
+ finalize();
+}
+
+
+
+MD5::MD5(ifstream& stream){
+
+ init(); // must called by all constructors
+ update (stream);
+ finalize();
+}
+
+
+
+unsigned char *MD5::raw_digest(){
+
+ uint1 *s = new uint1[16];
+
+ if (!finalized){
+ cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
+ "finalized the digest!" <<endl;
+ return ( (unsigned char*) "");
+ }
+
+ memcpy(s, digest, 16);
+ return s;
+}
+
+
+
+char *MD5::hex_digest(){
+
+ int i;
+ char *s= new char[33];
+
+ if (!finalized){
+ cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
+ "finalized the digest!" <<endl;
+ return "";
+ }
+
+ for (i=0; i<16; i++)
+ sprintf(s+i*2, "%02x", digest[i]);
+
+ s[32]='\0';
+
+ return s;
+}
+
+
+
+
+
+ostream& operator<<(ostream &stream, MD5 context){
+
+ stream << context.hex_digest();
+ return stream;
+}
+
+
+
+
+// PRIVATE METHODS:
+
+
+
+void MD5::init(){
+ finalized=0; // we just started!
+
+ // Nothing counted, so count=0
+ count[0] = 0;
+ count[1] = 0;
+
+ // Load magic initialization constants.
+ state[0] = 0x67452301;
+ state[1] = 0xefcdab89;
+ state[2] = 0x98badcfe;
+ state[3] = 0x10325476;
+}
+
+
+
+// Constants for MD5Transform routine.
+// Although we could use C++ style constants, defines are actually better,
+// since they let us easily evade scope clashes.
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+
+
+
+// MD5 basic transformation. Transforms state based on block.
+void MD5::transform (uint1 block[64]){
+
+ uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ decode (x, block, 64);
+
+ assert(!finalized); // not just a user error, since the method is private
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ // Zeroize sensitive information.
+ memset ( (uint1 *) x, 0, sizeof(x));
+
+}
+
+
+
+// Encodes input (UINT4) into output (unsigned char). Assumes len is
+// a multiple of 4.
+void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
+
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (uint1) (input[i] & 0xff);
+ output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
+ output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
+ output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
+ }
+}
+
+
+
+
+// Decodes input (unsigned char) into output (UINT4). Assumes len is
+// a multiple of 4.
+void MD5::decode (uint4 *output, uint1 *input, uint4 len){
+
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
+ (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
+}
+
+
+
+
+
+// Note: Replace "for loop" with standard memcpy if possible.
+void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
+
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+
+
+// Note: Replace "for loop" with standard memset if possible.
+void MD5::memset (uint1 *output, uint1 value, uint4 len){
+
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ output[i] = value;
+}
+
+
+
+// ROTATE_LEFT rotates x left n bits.
+
+inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
+ return (x << n) | (x >> (32-n)) ;
+}
+
+
+
+
+// F, G, H and I are basic MD5 functions.
+
+inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
+ return (x & y) | (~x & z);
+}
+
+inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
+ return (x & z) | (y & ~z);
+}
+
+inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
+ return x ^ y ^ z;
+}
+
+inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
+ return y ^ (x | ~z);
+}
+
+
+
+// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+// Rotation is separate from addition to prevent recomputation.
+
+
+inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac){
+ a += F(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+ }
+
+ inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac){
+ a += G(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+ }
+
+ inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac){
+ a += H(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+ }
+
+ inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac){
+ a += I(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+ }
--- /dev/null
+/**> HEADER FILES <**/
+#include "MacInput.h"
+#include "String.h"
+
+extern bool keyboardfrozen;
+
+/********************> IsKeyDown() <*****/
+Boolean IsKeyDown( unsigned char *keyMap, unsigned short theKey )
+{
+ if(keyboardfrozen)return 0;
+
+ static long keyMapIndex;
+ static Boolean isKeyDown;
+ static short bitToCheck;
+
+ // Calculate the key map index
+ keyMapIndex = keyMap[theKey/8];
+
+ // Calculate the individual bit to check
+ bitToCheck = theKey%8;
+
+ // Check the status of the key
+ isKeyDown = ( keyMapIndex >> bitToCheck ) & 0x01;
+
+ // Return the status of the key
+ return isKeyDown;
+
+}
+
+unsigned short CharToKey(char* which)
+{
+ if(!strcmp(which,"a")){
+ return MAC_A_KEY;
+ }
+ if(!strcmp(which,"b")){
+ return MAC_B_KEY;
+ }
+ if(!strcmp(which,"c")){
+ return MAC_C_KEY;
+ }
+ if(!strcmp(which,"d")){
+ return MAC_D_KEY;
+ }
+ if(!strcmp(which,"e")){
+ return MAC_E_KEY;
+ }
+ if(!strcmp(which,"f")){
+ return MAC_F_KEY;
+ }
+ if(!strcmp(which,"g")){
+ return MAC_G_KEY;
+ }
+ if(!strcmp(which,"h")){
+ return MAC_H_KEY;
+ }
+ if(!strcmp(which,"i")){
+ return MAC_I_KEY;
+ }
+ if(!strcmp(which,"j")){
+ return MAC_J_KEY;
+ }
+ if(!strcmp(which,"k")){
+ return MAC_K_KEY;
+ }
+ if(!strcmp(which,"l")){
+ return MAC_L_KEY;
+ }
+ if(!strcmp(which,"m")){
+ return MAC_M_KEY;
+ }
+ if(!strcmp(which,"n")){
+ return MAC_N_KEY;
+ }
+ if(!strcmp(which,"o")){
+ return MAC_O_KEY;
+ }
+ if(!strcmp(which,"p")){
+ return MAC_P_KEY;
+ }
+ if(!strcmp(which,"q")){
+ return MAC_Q_KEY;
+ }
+ if(!strcmp(which,"r")){
+ return MAC_R_KEY;
+ }
+ if(!strcmp(which,"s")){
+ return MAC_S_KEY;
+ }
+ if(!strcmp(which,"t")){
+ return MAC_T_KEY;
+ }
+ if(!strcmp(which,"u")){
+ return MAC_U_KEY;
+ }
+ if(!strcmp(which,"v")){
+ return MAC_V_KEY;
+ }
+ if(!strcmp(which,"w")){
+ return MAC_W_KEY;
+ }
+ if(!strcmp(which,"x")){
+ return MAC_X_KEY;
+ }
+ if(!strcmp(which,"y")){
+ return MAC_Y_KEY;
+ }
+ if(!strcmp(which,"z")){
+ return MAC_Z_KEY;
+ }
+ if(!strcmp(which,"0")){
+ return MAC_NUMPAD_0_KEY;
+ }
+ if(!strcmp(which,"1")){
+ return MAC_NUMPAD_1_KEY;
+ }
+ if(!strcmp(which,"2")){
+ return MAC_NUMPAD_2_KEY;
+ }
+ if(!strcmp(which,"3")){
+ return MAC_NUMPAD_3_KEY;
+ }
+ if(!strcmp(which,"4")){
+ return MAC_NUMPAD_4_KEY;
+ }
+ if(!strcmp(which,"5")){
+ return MAC_NUMPAD_5_KEY;
+ }
+ if(!strcmp(which,"6")){
+ return MAC_NUMPAD_6_KEY;
+ }
+ if(!strcmp(which,"7")){
+ return MAC_NUMPAD_7_KEY;
+ }
+ if(!strcmp(which,"8")){
+ return MAC_NUMPAD_8_KEY;
+ }
+ if(!strcmp(which,"9")){
+ return MAC_NUMPAD_9_KEY;
+ }
+ if(!strcmp(which,"enter")){
+ return MAC_ENTER_KEY;
+ }
+ if(!strcmp(which,"control")){
+ return MAC_CONTROL_KEY;
+ }
+ if(!strcmp(which,"return")){
+ return MAC_RETURN_KEY;
+ }
+ if(!strcmp(which,"space")){
+ return MAC_SPACE_KEY;
+ }
+ if(!strcmp(which,"shift")){
+ return MAC_SHIFT_KEY;
+ }
+ if(!strcmp(which,"uparrow")){
+ return MAC_ARROW_UP_KEY;
+ }
+ if(!strcmp(which,"downarrow")){
+ return MAC_ARROW_DOWN_KEY;
+ }
+ if(!strcmp(which,"leftarrow")){
+ return MAC_ARROW_LEFT_KEY;
+ }
+ if(!strcmp(which,"rightarrow")){
+ return MAC_ARROW_RIGHT_KEY;
+ }
+}
+
+char* KeyToChar(unsigned short which)
+{
+ static int i;
+
+ if(which==MAC_A_KEY){
+ return "a";
+ }
+ if(which==MAC_B_KEY){
+ return "b";
+ }
+ if(which==MAC_C_KEY){
+ return "c";
+ }
+ if(which==MAC_D_KEY){
+ return "d";
+ }
+ if(which==MAC_E_KEY){
+ return "e";
+ }
+ if(which==MAC_F_KEY){
+ return "f";
+ }
+ if(which==MAC_G_KEY){
+ return "g";
+ }
+ if(which==MAC_H_KEY){
+ return "h";
+ }
+ if(which==MAC_I_KEY){
+ return "i";
+ }
+ if(which==MAC_J_KEY){
+ return "j";
+ }
+ if(which==MAC_K_KEY){
+ return "k";
+ }
+ if(which==MAC_L_KEY){
+ return "l";
+ }
+ if(which==MAC_M_KEY){
+ return "m";
+ }
+ if(which==MAC_N_KEY){
+ return "n";
+ }
+ if(which==MAC_O_KEY){
+ return "o";
+ }
+ if(which==MAC_P_KEY){
+ return "p";
+ }
+ if(which==MAC_Q_KEY){
+ return "q";
+ }
+ if(which==MAC_R_KEY){
+ return "r";
+ }
+ if(which==MAC_S_KEY){
+ return "s";
+ }
+ if(which==MAC_T_KEY){
+ return "t";
+ }
+ if(which==MAC_U_KEY){
+ return "u";
+ }
+ if(which==MAC_V_KEY){
+ return "v";
+ }
+ if(which==MAC_W_KEY){
+ return "w";
+ }
+ if(which==MAC_X_KEY){
+ return "x";
+ }
+ if(which==MAC_Y_KEY){
+ return "y";
+ }
+ if(which==MAC_Z_KEY){
+ return "z";
+ }
+ if(which==MAC_NUMPAD_1_KEY){
+ return "1";
+ }
+ if(which==MAC_NUMPAD_2_KEY){
+ return "2";
+ }
+ if(which==MAC_NUMPAD_3_KEY){
+ return "3";
+ }
+ if(which==MAC_NUMPAD_4_KEY){
+ return "4";
+ }
+ if(which==MAC_NUMPAD_5_KEY){
+ return "5";
+ }
+ if(which==MAC_NUMPAD_6_KEY){
+ return "6";
+ }
+ if(which==MAC_NUMPAD_7_KEY){
+ return "7";
+ }
+ if(which==MAC_NUMPAD_8_KEY){
+ return "8";
+ }
+ if(which==MAC_NUMPAD_9_KEY){
+ return "9";
+ }
+ if(which==MAC_ENTER_KEY){
+ return "enter";
+ }
+ if(which==MAC_NUMPAD_0_KEY){
+ return "0";
+ }
+ if(which==MAC_1_KEY){
+ return "1";
+ }
+ if(which==MAC_2_KEY){
+ return "2";
+ }
+ if(which==MAC_3_KEY){
+ return "3";
+ }
+ if(which==MAC_4_KEY){
+ return "4";
+ }
+ if(which==MAC_5_KEY){
+ return "5";
+ }
+ if(which==MAC_6_KEY){
+ return "6";
+ }
+ if(which==MAC_7_KEY){
+ return "7";
+ }
+ if(which==MAC_8_KEY){
+ return "8";
+ }
+ if(which==MAC_9_KEY){
+ return "9";
+ }
+ if(which==MAC_0_KEY){
+ return "0";
+ }
+ if(which==MAC_F1_KEY){
+ return "F1";
+ }
+ if(which==MAC_F2_KEY){
+ return "F2";
+ }
+ if(which==MAC_F3_KEY){
+ return "F3";
+ }
+ if(which==MAC_F4_KEY){
+ return "F4";
+ }
+ if(which==MAC_F5_KEY){
+ return "F5";
+ }
+ if(which==MAC_F6_KEY){
+ return "F6";
+ }
+ if(which==MAC_F7_KEY){
+ return "F7";
+ }
+ if(which==MAC_F8_KEY){
+ return "F8";
+ }
+ if(which==MAC_F9_KEY){
+ return "F9";
+ }
+ if(which==MAC_F10_KEY){
+ return "F10";
+ }
+ if(which==MAC_F11_KEY){
+ return "F11";
+ }
+ if(which==MAC_F12_KEY){
+ return "F12";
+ }
+ if(which==MAC_ESCAPE_KEY){
+ return "escape";
+ }
+ if(which==MAC_DELETE_KEY){
+ return "backspace";
+ }
+ if(which==MAC_TAB_KEY){
+ return "tab";
+ }
+ if(which==MAC_TILDE_KEY){
+ return "`";
+ }
+ if(which==MAC_CAPS_LOCK_KEY){
+ return "caps lock";
+ }
+ if(which==MAC_COMMAND_KEY){
+ return "command";
+ }
+ if(which==MAC_OPTION_KEY){
+ return "option";
+ }
+ if(which==MAC_DEL_KEY){
+ return "delete";
+ }
+ if(which==MAC_INSERT_KEY){
+ return "insert";
+ }
+ if(which==MAC_HOME_KEY){
+ return "home";
+ }
+ if(which==MAC_END_KEY){
+ return "end";
+ }
+ if(which==MAC_PAGE_UP_KEY){
+ return "page up";
+ }
+ if(which==MAC_PAGE_DOWN_KEY){
+ return "page down";
+ }
+ if(which==MAC_NUMPAD_CLEAR_KEY){
+ return "clear";
+ }
+ if(which==MAC_CONTROL_KEY){
+ return "control";
+ }
+ if(which==MAC_SPACE_KEY){
+ return "space";
+ }
+ if(which==MAC_RETURN_KEY){
+ return "return";
+ }
+ if(which==MAC_SHIFT_KEY){
+ return "shift";
+ }
+ if(which==MAC_ARROW_UP_KEY){
+ return "uparrow";
+ }
+ if(which==MAC_ARROW_DOWN_KEY){
+ return "downarrow";
+ }
+ if(which==MAC_ARROW_LEFT_KEY){
+ return "leftarrow";
+ }
+ if(which==MAC_ARROW_RIGHT_KEY){
+ return "rightarrow";
+ }
+ if(which==MAC_MINUS_KEY||which==MAC_NUMPAD_MINUS_KEY){
+ return "-";
+ }
+ if(which==MAC_PLUS_KEY||which==MAC_NUMPAD_EQUALS_KEY){
+ return "=";
+ }
+ if(which==MAC_NUMPAD_PLUS_KEY){
+ return "+";
+ }
+ if(which==MAC_NUMPAD_ASTERISK_KEY){
+ return "*";
+ }
+ if(which==MAC_SLASH_KEY||which==MAC_NUMPAD_SLASH_KEY){
+ return "/";
+ }
+ if(which==MAC_BACKSLASH_KEY){
+ return "\\";
+ }
+ if(which==MAC_LEFTBRACKET_KEY){
+ return "[";
+ }
+ if(which==MAC_RIGHTBRACKET_KEY){
+ return "]";
+ }
+ if(which==MAC_PERIOD_KEY||which==MAC_NUMPAD_PERIOD_KEY){
+ return ".";
+ }
+ if(which==MAC_COMMA_KEY){
+ return ",";
+ }
+ if(which==MAC_APOSTROPHE_KEY){
+ return "\"";
+ }
+ if(which==MAC_SEMICOLON_KEY){
+ return ";";
+ }
+ return "unknown";
+}
+
+char KeyToSingleChar(unsigned short which)
+{
+ static int i;
+
+ if(which==MAC_A_KEY){
+ return 'a';
+ }
+ if(which==MAC_B_KEY){
+ return 'b';
+ }
+ if(which==MAC_C_KEY){
+ return 'c';
+ }
+ if(which==MAC_D_KEY){
+ return 'd';
+ }
+ if(which==MAC_E_KEY){
+ return 'e';
+ }
+ if(which==MAC_F_KEY){
+ return 'f';
+ }
+ if(which==MAC_G_KEY){
+ return 'g';
+ }
+ if(which==MAC_H_KEY){
+ return 'h';
+ }
+ if(which==MAC_I_KEY){
+ return 'i';
+ }
+ if(which==MAC_J_KEY){
+ return 'j';
+ }
+ if(which==MAC_K_KEY){
+ return 'k';
+ }
+ if(which==MAC_L_KEY){
+ return 'l';
+ }
+ if(which==MAC_M_KEY){
+ return 'm';
+ }
+ if(which==MAC_N_KEY){
+ return 'n';
+ }
+ if(which==MAC_O_KEY){
+ return 'o';
+ }
+ if(which==MAC_P_KEY){
+ return 'p';
+ }
+ if(which==MAC_Q_KEY){
+ return 'q';
+ }
+ if(which==MAC_R_KEY){
+ return 'r';
+ }
+ if(which==MAC_S_KEY){
+ return 's';
+ }
+ if(which==MAC_T_KEY){
+ return 't';
+ }
+ if(which==MAC_U_KEY){
+ return 'u';
+ }
+ if(which==MAC_V_KEY){
+ return 'v';
+ }
+ if(which==MAC_W_KEY){
+ return 'w';
+ }
+ if(which==MAC_X_KEY){
+ return 'x';
+ }
+ if(which==MAC_Y_KEY){
+ return 'y';
+ }
+ if(which==MAC_Z_KEY){
+ return 'z';
+ }
+ if(which==MAC_NUMPAD_1_KEY){
+ return '1';
+ }
+ if(which==MAC_NUMPAD_2_KEY){
+ return '2';
+ }
+ if(which==MAC_NUMPAD_3_KEY){
+ return '3';
+ }
+ if(which==MAC_NUMPAD_4_KEY){
+ return '4';
+ }
+ if(which==MAC_NUMPAD_5_KEY){
+ return '5';
+ }
+ if(which==MAC_NUMPAD_6_KEY){
+ return '6';
+ }
+ if(which==MAC_NUMPAD_7_KEY){
+ return '7';
+ }
+ if(which==MAC_NUMPAD_8_KEY){
+ return '8';
+ }
+ if(which==MAC_NUMPAD_9_KEY){
+ return '9';
+ }
+ if(which==MAC_NUMPAD_0_KEY){
+ return '0';
+ }
+ if(which==MAC_1_KEY){
+ return '1';
+ }
+ if(which==MAC_2_KEY){
+ return '2';
+ }
+ if(which==MAC_3_KEY){
+ return '3';
+ }
+ if(which==MAC_4_KEY){
+ return '4';
+ }
+ if(which==MAC_5_KEY){
+ return '5';
+ }
+ if(which==MAC_6_KEY){
+ return '6';
+ }
+ if(which==MAC_7_KEY){
+ return '7';
+ }
+ if(which==MAC_8_KEY){
+ return '8';
+ }
+ if(which==MAC_9_KEY){
+ return '9';
+ }
+ if(which==MAC_0_KEY){
+ return '0';
+ }
+ if(which==MAC_SPACE_KEY){
+ return ' ';
+ }
+ if(which==MAC_MINUS_KEY||which==MAC_NUMPAD_MINUS_KEY){
+ return '-';
+ }
+ if(which==MAC_PLUS_KEY||which==MAC_NUMPAD_EQUALS_KEY){
+ return '=';
+ }
+ if(which==MAC_NUMPAD_PLUS_KEY){
+ return '+';
+ }
+ if(which==MAC_NUMPAD_ASTERISK_KEY){
+ return '*';
+ }
+ if(which==MAC_SLASH_KEY||which==MAC_NUMPAD_SLASH_KEY){
+ return '/';
+ }
+ if(which==MAC_BACKSLASH_KEY){
+ return '\\';
+ }
+ if(which==MAC_LEFTBRACKET_KEY){
+ return '[';
+ }
+ if(which==MAC_RIGHTBRACKET_KEY){
+ return ']';
+ }
+ if(which==MAC_PERIOD_KEY||which==MAC_NUMPAD_PERIOD_KEY){
+ return '.';
+ }
+ if(which==MAC_COMMA_KEY){
+ return ',';
+ }
+ if(which==MAC_APOSTROPHE_KEY){
+ return '\'';
+ }
+ if(which==MAC_SEMICOLON_KEY){
+ return ';';
+ }
+ return '\0';
+}
+
+char Shift(char which)
+{
+ static int i;
+
+ if(which=='a'){
+ return 'A';
+ }
+ if(which=='b'){
+ return 'B';
+ }
+ if(which=='c'){
+ return 'C';
+ }
+ if(which=='d'){
+ return 'D';
+ }
+ if(which=='e'){
+ return 'E';
+ }
+ if(which=='f'){
+ return 'F';
+ }
+ if(which=='g'){
+ return 'G';
+ }
+ if(which=='h'){
+ return 'H';
+ }
+ if(which=='e'){
+ return 'E';
+ }
+ if(which=='f'){
+ return 'F';
+ }
+ if(which=='g'){
+ return 'G';
+ }
+ if(which=='h'){
+ return 'H';
+ }
+ if(which=='i'){
+ return 'I';
+ }
+ if(which=='j'){
+ return 'J';
+ }
+ if(which=='k'){
+ return 'K';
+ }
+ if(which=='l'){
+ return 'L';
+ }
+ if(which=='m'){
+ return 'M';
+ }
+ if(which=='n'){
+ return 'N';
+ }
+ if(which=='o'){
+ return 'O';
+ }
+ if(which=='p'){
+ return 'P';
+ }
+ if(which=='q'){
+ return 'Q';
+ }
+ if(which=='r'){
+ return 'R';
+ }
+ if(which=='s'){
+ return 'S';
+ }
+ if(which=='t'){
+ return 'T';
+ }
+ if(which=='u'){
+ return 'U';
+ }
+ if(which=='v'){
+ return 'V';
+ }
+ if(which=='w'){
+ return 'W';
+ }
+ if(which=='x'){
+ return 'X';
+ }
+ if(which=='y'){
+ return 'Y';
+ }
+ if(which=='z'){
+ return 'Z';
+ }
+ if(which=='1'){
+ return '!';
+ }
+ if(which=='2'){
+ return '@';
+ }
+ if(which=='3'){
+ return '#';
+ }
+ if(which=='4'){
+ return '$';
+ }
+ if(which=='5'){
+ return '%';
+ }
+ if(which=='6'){
+ return '^';
+ }
+ if(which=='7'){
+ return '&';
+ }
+ if(which=='8'){
+ return '*';
+ }
+ if(which=='9'){
+ return '(';
+ }
+ if(which=='0'){
+ return ')';
+ }
+ if(which=='-'){
+ return '_';
+ }
+ if(which=='='){
+ return '+';
+ }
+ if(which=='['){
+ return '{';
+ }
+ if(which==']'){
+ return '}';
+ }
+ if(which=='\\'){
+ return '|';
+ }
+ if(which=='.'){
+ return '>';
+ }
+ if(which==','){
+ return '<';
+ }
+ if(which=='/'){
+ return '?';
+ }
+ if(which==';'){
+ return ':';
+ }
+ if(which=='\''){
+ return '\"';
+ }
+ return which;
+}
+
+bool Compare(char *thestring, char *tocompare, int start, int end)
+{
+ static int i;
+ for(i=start;i<=end;i++){
+ if(thestring[i]!=tocompare[i-start]&&thestring[i]!=tocompare[i-start]+'A'-'a')return 0;
+ }
+ return 1;
+}
\ No newline at end of file
--- /dev/null
+#ifndef _MACINPUT_H_
+#define _MACINPUT_H_
+
+/**> HEADER FILES <**/
+#include <stdlib.h>
+#include <stdio.h>
+#include <CursorDevices.h> //Mouse
+
+/**> CONSTANT DECLARATIONS <**/
+// Mac Keyboard Codes
+#define MAC_1_KEY 0x12
+#define MAC_2_KEY 0x13
+#define MAC_3_KEY 0x14
+#define MAC_4_KEY 0x15
+#define MAC_5_KEY 0x17
+#define MAC_6_KEY 0x16
+#define MAC_7_KEY 0x1A
+#define MAC_8_KEY 0x1C
+#define MAC_9_KEY 0x19
+#define MAC_0_KEY 0x1D
+#define MAC_NUMPAD_1_KEY 0x53
+#define MAC_NUMPAD_2_KEY 0x54
+#define MAC_NUMPAD_3_KEY 0x55
+#define MAC_NUMPAD_4_KEY 0x56
+#define MAC_NUMPAD_5_KEY 0x57
+#define MAC_NUMPAD_6_KEY 0x58
+#define MAC_NUMPAD_7_KEY 0x59
+#define MAC_NUMPAD_8_KEY 0x5B
+#define MAC_NUMPAD_9_KEY 0x5C
+#define MAC_NUMPAD_0_KEY 0x52
+#define MAC_A_KEY 0x00
+#define MAC_B_KEY 0x0B
+#define MAC_C_KEY 0x08
+#define MAC_D_KEY 0x02
+#define MAC_E_KEY 0x0E
+#define MAC_F_KEY 0x03
+#define MAC_G_KEY 0x05
+#define MAC_H_KEY 0x04
+#define MAC_I_KEY 0x22
+#define MAC_J_KEY 0x26
+#define MAC_K_KEY 0x28
+#define MAC_L_KEY 0x25
+#define MAC_M_KEY 0x2E
+#define MAC_N_KEY 0x2D
+#define MAC_O_KEY 0x1F
+#define MAC_P_KEY 0x23
+#define MAC_Q_KEY 0x0C
+#define MAC_R_KEY 0x0F
+#define MAC_S_KEY 0x01
+#define MAC_T_KEY 0x11
+#define MAC_U_KEY 0x20
+#define MAC_V_KEY 0x09
+#define MAC_W_KEY 0x0D
+#define MAC_X_KEY 0x07
+#define MAC_Y_KEY 0x10
+#define MAC_Z_KEY 0x06
+#define MAC_F1_KEY 0x7A
+#define MAC_F2_KEY 0x78
+#define MAC_F3_KEY 0x63
+#define MAC_F4_KEY 0x76
+#define MAC_F5_KEY 0x60
+#define MAC_F6_KEY 0x61
+#define MAC_F7_KEY 0x62
+#define MAC_F8_KEY 0x64
+#define MAC_F9_KEY 0x65
+#define MAC_F10_KEY 0x6D
+#define MAC_F11_KEY 0x67
+#define MAC_F12_KEY 0x6F
+#define MAC_RETURN_KEY 0x24
+#define MAC_ENTER_KEY 0x4C
+#define MAC_TAB_KEY 0x30
+#define MAC_SPACE_KEY 0x31
+#define MAC_DELETE_KEY 0x33
+#define MAC_ESCAPE_KEY 0x35
+#define MAC_COMMAND_KEY 0x37
+#define MAC_SHIFT_KEY 0x38
+#define MAC_CAPS_LOCK_KEY 0x39
+#define MAC_OPTION_KEY 0x3A
+#define MAC_CONTROL_KEY 0x3B
+#define MAC_PAGE_UP_KEY 0x74
+#define MAC_PAGE_DOWN_KEY 0x79
+#define MAC_INSERT_KEY 0x72
+#define MAC_DEL_KEY 0x75
+#define MAC_HOME_KEY 0x73
+#define MAC_END_KEY 0x77
+#define MAC_LEFT_BRACKET_KEY 0x21
+#define MAC_RIGHT_BRACKET_KEY 0x1E
+#define MAC_ARROW_UP_KEY 0x7E
+#define MAC_ARROW_DOWN_KEY 0x7D
+#define MAC_ARROW_LEFT_KEY 0x7B
+#define MAC_ARROW_RIGHT_KEY 0x7C
+#define MAC_TILDE_KEY 0x32
+#define MAC_MINUS_KEY 0x1B
+#define MAC_PLUS_KEY 0x18
+#define MAC_SLASH_KEY 0x2C
+#define MAC_PERIOD_KEY 0x2F
+#define MAC_COMMA_KEY 0x2B
+#define MAC_BACKSLASH_KEY 0x2A
+#define MAC_LEFTBRACKET_KEY 0x21
+#define MAC_RIGHTBRACKET_KEY 0x1E
+#define MAC_NUMPAD_CLEAR_KEY 0x47#define MAC_NUMPAD_MINUS_KEY 0x4E
+#define MAC_NUMPAD_EQUALS_KEY 0x51
+#define MAC_NUMPAD_PLUS_KEY 0x45
+#define MAC_NUMPAD_SLASH_KEY 0x4B
+#define MAC_NUMPAD_ASTERISK_KEY 0x43
+#define MAC_NUMPAD_ENTER_KEY 0x4C
+#define MAC_NUMPAD_PERIOD_KEY 0x41
+#define MAC_SEMICOLON_KEY 0x29
+#define MAC_APOSTROPHE_KEY 0x27
+
+/**> FUNCTION PROTOTYPES <**/
+Boolean IsKeyDown( unsigned char *keyMap, unsigned short theKey );
+void InitMouse();
+void MoveMouse(int xcoord, int ycoord, Point *mouseloc);
+void RefreshMouse(Point *mouseloc);
+void DisposeMouse();
+unsigned short CharToKey(char* which);
+char* KeyToChar(unsigned short which);
+char KeyToSingleChar(unsigned short which);
+char Shift(char which);
+bool Compare(char *thestring, char *tocompare, int start, int end);
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "Models.h"
+//#include "altivec.h"
+#include "Game.h"
+
+extern float multiplier;
+extern float viewdistance;
+extern XYZ viewer;
+extern float fadestart;
+extern float texdetail;
+extern bool decals;
+extern int loadscreencolor;
+
+#include "Game.h"
+extern Game * pgame;
+extern bool visibleloading;
+//Functions
+void *allocate_aligned(size_t pointer_size, size_t byte_alignment)
+{
+ uintptr_t pointer = (uintptr_t)malloc(pointer_size + byte_alignment + 1);
+ uintptr_t aligned_pointer = (pointer + byte_alignment + 1);
+ aligned_pointer -= (aligned_pointer % byte_alignment);
+ *(uint8_t *)(aligned_pointer - 1) = (aligned_pointer - pointer);
+ return (void *)aligned_pointer;
+}
+
+void free_aligned(void *aligned_pointer)
+{
+ free((uint8_t *)(aligned_pointer) - *((uint8_t *)(aligned_pointer) - 1));
+}
+
+void dealloc(void* param){
+ free(param);
+ param=0;
+}
+
+int Model::LineCheck(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+{
+ static int j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+
+ *p1=*p1-*move;
+ *p2=*p2-*move;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
+ if(!sphere_line_intersection(p1,p2,&boundingspherecenter,
+ &boundingsphereradius))return -1;
+ firstintersecting=-1;
+
+ for (j=0;j<TriangleNum;j++){
+ intersecting=LineFacetd(p1,p2,&vertex[Triangles[j].vertex[0]],&vertex[Triangles[j].vertex[1]],&vertex[Triangles[j].vertex[2]],&facenormals[j],&point);
+ distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+ }
+
+ if(*rotate)*p=DoRotation(*p,0,*rotate,0);
+ *p=*p+*move;
+ return firstintersecting;
+}
+
+int Model::LineCheckSlide(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+{
+ static int j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+
+ *p1=*p1-*move;
+ *p2=*p2-*move;
+ if(!sphere_line_intersection(p1,p2,&boundingspherecenter,
+ &boundingsphereradius))return -1;
+ firstintersecting=-1;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
+
+ for (j=0;j<TriangleNum;j++){
+ intersecting=LineFacetd(p1,p2,&vertex[Triangles[j].vertex[0]],&vertex[Triangles[j].vertex[1]],&vertex[Triangles[j].vertex[2]],&facenormals[j],&point);
+ distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j;}
+ }
+
+ distance=abs((facenormals[firstintersecting].x*p2->x)+(facenormals[firstintersecting].y*p2->y)+(facenormals[firstintersecting].z*p2->z)-((facenormals[firstintersecting].x*vertex[Triangles[firstintersecting].vertex[0]].x)+(facenormals[firstintersecting].y*vertex[Triangles[firstintersecting].vertex[0]].y)+(facenormals[firstintersecting].z*vertex[Triangles[firstintersecting].vertex[0]].z)));
+ *p2-=facenormals[firstintersecting]*distance;
+
+ if(*rotate)*p2=DoRotation(*p2,0,*rotate,0);
+ *p2=*p2+*move;
+ return firstintersecting;
+}
+
+int Model::LineCheckPossible(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+{
+ static int j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+
+ *p1=*p1-*move;
+ *p2=*p2-*move;
+ if(!sphere_line_intersection(p1,p2,&boundingspherecenter,
+ &boundingsphereradius))return -1;
+ firstintersecting=-1;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
+
+ if(numpossible>0&&numpossible<TriangleNum)
+ for (j=0;j<numpossible;j++){
+ if(possible[j]>=0&&possible[j]<TriangleNum){
+ intersecting=LineFacetd(p1,p2,&vertex[Triangles[possible[j]].vertex[0]],&vertex[Triangles[possible[j]].vertex[1]],&vertex[Triangles[possible[j]].vertex[2]],&facenormals[possible[j]],&point);
+ distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=possible[j]; *p=point;}
+ }
+ }
+
+ if(*rotate)*p=DoRotation(*p,0,*rotate,0);
+ *p=*p+*move;
+ return firstintersecting;
+}
+
+int Model::LineCheckSlidePossible(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
+{
+ static int j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+
+ *p1=*p1-*move;
+ *p2=*p2-*move;
+ if(!sphere_line_intersection(p1,p2,&boundingspherecenter,
+ &boundingsphereradius))return -1;
+ firstintersecting=-1;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
+
+ if(numpossible)
+ for (j=0;j<numpossible;j++){
+ if(possible[j]>=0&&possible[j]<TriangleNum){
+ intersecting=LineFacetd(p1,p2,&vertex[Triangles[possible[j]].vertex[0]],&vertex[Triangles[possible[j]].vertex[1]],&vertex[Triangles[possible[j]].vertex[2]],&facenormals[possible[j]],&point);
+ distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=possible[j];}
+ }
+ }
+
+ if(firstintersecting>0){
+ distance=abs((facenormals[firstintersecting].x*p2->x)+(facenormals[firstintersecting].y*p2->y)+(facenormals[firstintersecting].z*p2->z)-((facenormals[firstintersecting].x*vertex[Triangles[firstintersecting].vertex[0]].x)+(facenormals[firstintersecting].y*vertex[Triangles[firstintersecting].vertex[0]].y)+(facenormals[firstintersecting].z*vertex[Triangles[firstintersecting].vertex[0]].z)));
+ *p2-=facenormals[firstintersecting]*distance;
+ }
+
+ if(*rotate)*p2=DoRotation(*p2,0,*rotate,0);
+ *p2=*p2+*move;
+ return firstintersecting;
+}
+
+int Model::SphereCheck(XYZ *p1,float radius, XYZ *p, XYZ *move, float *rotate)
+{
+ static int i,j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+ static XYZ oldp1;
+ static XYZ start,end;
+
+ firstintersecting=-1;
+
+ oldp1=*p1;
+ *p1=*p1-*move;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(findDistancefast(p1,&boundingspherecenter)>radius*radius+boundingsphereradius*boundingsphereradius)return -1;
+
+ for(i=0;i<4;i++){
+ for (j=0;j<TriangleNum;j++){
+ intersecting=0;
+ distance=abs((facenormals[j].x*p1->x)+(facenormals[j].y*p1->y)+(facenormals[j].z*p1->z)-((facenormals[j].x*vertex[Triangles[j].vertex[0]].x)+(facenormals[j].y*vertex[Triangles[j].vertex[0]].y)+(facenormals[j].z*vertex[Triangles[j].vertex[0]].z)));
+ if(distance<radius){
+ point=*p1-facenormals[j]*distance;
+ if(PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))intersecting=1;
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[0]],
+ &vertex[Triangles[j].vertex[1]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[1]],
+ &vertex[Triangles[j].vertex[2]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[0]],
+ &vertex[Triangles[j].vertex[2]],
+ p1, &radius);
+ if(intersecting){
+ *p1+=facenormals[j]*(distance-radius);
+ /*start=*p1;
+ end=*p1;
+ end.y-=radius;
+ if(LineFacetd(&start,&end,&vertex[Triangles[j].vertex[0]],&vertex[Triangles[j].vertex[1]],&vertex[Triangles[j].vertex[2]],&facenormals[j],&point)){
+ p1->y=point.y+radius;
+ }*/
+ }
+ }
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+ }
+ }
+ if(*rotate)*p=DoRotation(*p,0,*rotate,0);
+ *p=*p+*move;
+ if(*rotate)*p1=DoRotation(*p1,0,*rotate,0);
+ *p1+=*move;
+ return firstintersecting;
+}
+
+int Model::SphereCheckPossible(XYZ *p1,float radius, XYZ *move, float *rotate)
+{
+ static int i,j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+ static XYZ oldp1;
+ static XYZ start,end;
+
+ firstintersecting=-1;
+
+ oldp1=*p1;
+ *p1=*p1-*move;
+
+ numpossible=0;
+
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ if(findDistancefast(p1,&boundingspherecenter)>radius*radius+boundingsphereradius*boundingsphereradius){*p1=oldp1; return -1;}
+
+ for (j=0;j<TriangleNum;j++){
+ intersecting=0;
+ distance=abs((facenormals[j].x*p1->x)+(facenormals[j].y*p1->y)+(facenormals[j].z*p1->z)-((facenormals[j].x*vertex[Triangles[j].vertex[0]].x)+(facenormals[j].y*vertex[Triangles[j].vertex[0]].y)+(facenormals[j].z*vertex[Triangles[j].vertex[0]].z)));
+ if(distance<radius){
+ point=*p1-facenormals[j]*distance;
+ if(PointInTriangle( &point, facenormals[j], &vertex[Triangles[j].vertex[0]], &vertex[Triangles[j].vertex[1]], &vertex[Triangles[j].vertex[2]]))intersecting=1;
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[0]],
+ &vertex[Triangles[j].vertex[1]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[1]],
+ &vertex[Triangles[j].vertex[2]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&vertex[Triangles[j].vertex[0]],
+ &vertex[Triangles[j].vertex[2]],
+ p1, &radius);
+ if(intersecting){
+ //if(j>=0&&j<TriangleNum)
+ possible[numpossible]=j;
+ numpossible++;
+ }
+ }
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j;}
+ }
+ if(*rotate)*p1=DoRotation(*p1,0,*rotate,0);
+ *p1+=*move;
+ return firstintersecting;
+}
+
+
+void Model::UpdateVertexArray(){
+ if(type!=normaltype&&type!=decalstype)return;
+ static int i;
+ static int j;
+ if(!flat)
+ for(i=0;i<TriangleNum;i++){
+ j=i*24;
+ vArray[j+0]=Triangles[i].gx[0];
+ vArray[j+1]=Triangles[i].gy[0];
+ vArray[j+2]=normals[Triangles[i].vertex[0]].x;
+ vArray[j+3]=normals[Triangles[i].vertex[0]].y;
+ vArray[j+4]=normals[Triangles[i].vertex[0]].z;
+ vArray[j+5]=vertex[Triangles[i].vertex[0]].x;
+ vArray[j+6]=vertex[Triangles[i].vertex[0]].y;
+ vArray[j+7]=vertex[Triangles[i].vertex[0]].z;
+
+ vArray[j+8]=Triangles[i].gx[1];
+ vArray[j+9]=Triangles[i].gy[1];
+ vArray[j+10]=normals[Triangles[i].vertex[1]].x;
+ vArray[j+11]=normals[Triangles[i].vertex[1]].y;
+ vArray[j+12]=normals[Triangles[i].vertex[1]].z;
+ vArray[j+13]=vertex[Triangles[i].vertex[1]].x;
+ vArray[j+14]=vertex[Triangles[i].vertex[1]].y;
+ vArray[j+15]=vertex[Triangles[i].vertex[1]].z;
+
+ vArray[j+16]=Triangles[i].gx[2];
+ vArray[j+17]=Triangles[i].gy[2];
+ vArray[j+18]=normals[Triangles[i].vertex[2]].x;
+ vArray[j+19]=normals[Triangles[i].vertex[2]].y;
+ vArray[j+20]=normals[Triangles[i].vertex[2]].z;
+ vArray[j+21]=vertex[Triangles[i].vertex[2]].x;
+ vArray[j+22]=vertex[Triangles[i].vertex[2]].y;
+ vArray[j+23]=vertex[Triangles[i].vertex[2]].z;
+ }
+ if(flat)
+ for(i=0;i<TriangleNum;i++){
+ j=i*24;
+ vArray[j+0]=Triangles[i].gx[0];
+ vArray[j+1]=Triangles[i].gy[0];
+ vArray[j+2]=facenormals[i].x*-1;
+ vArray[j+3]=facenormals[i].y*-1;
+ vArray[j+4]=facenormals[i].z*-1;
+ vArray[j+5]=vertex[Triangles[i].vertex[0]].x;
+ vArray[j+6]=vertex[Triangles[i].vertex[0]].y;
+ vArray[j+7]=vertex[Triangles[i].vertex[0]].z;
+
+ vArray[j+8]=Triangles[i].gx[1];
+ vArray[j+9]=Triangles[i].gy[1];
+ vArray[j+10]=facenormals[i].x*-1;
+ vArray[j+11]=facenormals[i].y*-1;
+ vArray[j+12]=facenormals[i].z*-1;
+ vArray[j+13]=vertex[Triangles[i].vertex[1]].x;
+ vArray[j+14]=vertex[Triangles[i].vertex[1]].y;
+ vArray[j+15]=vertex[Triangles[i].vertex[1]].z;
+
+ vArray[j+16]=Triangles[i].gx[2];
+ vArray[j+17]=Triangles[i].gy[2];
+ vArray[j+18]=facenormals[i].x*-1;
+ vArray[j+19]=facenormals[i].y*-1;
+ vArray[j+20]=facenormals[i].z*-1;
+ vArray[j+21]=vertex[Triangles[i].vertex[2]].x;
+ vArray[j+22]=vertex[Triangles[i].vertex[2]].y;
+ vArray[j+23]=vertex[Triangles[i].vertex[2]].z;
+
+ }
+}
+
+void Model::UpdateVertexArrayNoTex(){
+ if(type!=normaltype&&type!=decalstype)return;
+ static int i;
+ static int j;
+ if(!flat)
+ for(i=0;i<TriangleNum;i++){
+ j=i*24;
+ vArray[j+2]=normals[Triangles[i].vertex[0]].x;
+ vArray[j+3]=normals[Triangles[i].vertex[0]].y;
+ vArray[j+4]=normals[Triangles[i].vertex[0]].z;
+ vArray[j+5]=vertex[Triangles[i].vertex[0]].x;
+ vArray[j+6]=vertex[Triangles[i].vertex[0]].y;
+ vArray[j+7]=vertex[Triangles[i].vertex[0]].z;
+
+ vArray[j+10]=normals[Triangles[i].vertex[1]].x;
+ vArray[j+11]=normals[Triangles[i].vertex[1]].y;
+ vArray[j+12]=normals[Triangles[i].vertex[1]].z;
+ vArray[j+13]=vertex[Triangles[i].vertex[1]].x;
+ vArray[j+14]=vertex[Triangles[i].vertex[1]].y;
+ vArray[j+15]=vertex[Triangles[i].vertex[1]].z;
+
+ vArray[j+18]=normals[Triangles[i].vertex[2]].x;
+ vArray[j+19]=normals[Triangles[i].vertex[2]].y;
+ vArray[j+20]=normals[Triangles[i].vertex[2]].z;
+ vArray[j+21]=vertex[Triangles[i].vertex[2]].x;
+ vArray[j+22]=vertex[Triangles[i].vertex[2]].y;
+ vArray[j+23]=vertex[Triangles[i].vertex[2]].z;
+ }
+ if(flat)
+ for(i=0;i<TriangleNum;i++){
+ j=i*24;
+ vArray[j+2]=facenormals[i].x*-1;
+ vArray[j+3]=facenormals[i].y*-1;
+ vArray[j+4]=facenormals[i].z*-1;
+ vArray[j+5]=vertex[Triangles[i].vertex[0]].x;
+ vArray[j+6]=vertex[Triangles[i].vertex[0]].y;
+ vArray[j+7]=vertex[Triangles[i].vertex[0]].z;
+
+ vArray[j+10]=facenormals[i].x*-1;
+ vArray[j+11]=facenormals[i].y*-1;
+ vArray[j+12]=facenormals[i].z*-1;
+ vArray[j+13]=vertex[Triangles[i].vertex[1]].x;
+ vArray[j+14]=vertex[Triangles[i].vertex[1]].y;
+ vArray[j+15]=vertex[Triangles[i].vertex[1]].z;
+
+ vArray[j+18]=facenormals[i].x*-1;
+ vArray[j+19]=facenormals[i].y*-1;
+ vArray[j+20]=facenormals[i].z*-1;
+ vArray[j+21]=vertex[Triangles[i].vertex[2]].x;
+ vArray[j+22]=vertex[Triangles[i].vertex[2]].y;
+ vArray[j+23]=vertex[Triangles[i].vertex[2]].z;
+ }
+}
+
+void Model::UpdateVertexArrayNoTexNoNorm(){
+ if(type!=normaltype&&type!=decalstype)return;
+ static int i;
+ static int j;
+ for(i=0;i<TriangleNum;i++){
+ j=i*24;
+ vArray[j+5]=vertex[Triangles[i].vertex[0]].x;
+ vArray[j+6]=vertex[Triangles[i].vertex[0]].y;
+ vArray[j+7]=vertex[Triangles[i].vertex[0]].z;
+
+ vArray[j+13]=vertex[Triangles[i].vertex[1]].x;
+ vArray[j+14]=vertex[Triangles[i].vertex[1]].y;
+ vArray[j+15]=vertex[Triangles[i].vertex[1]].z;
+
+ vArray[j+21]=vertex[Triangles[i].vertex[2]].x;
+ vArray[j+22]=vertex[Triangles[i].vertex[2]].y;
+ vArray[j+23]=vertex[Triangles[i].vertex[2]].z;
+ }
+}
+
+bool Model::loadnotex(char *filename )
+{
+ FILE *tfile;
+ long i;
+
+ int oldvertexNum,oldTriangleNum;
+ oldvertexNum=vertexNum;
+ oldTriangleNum=TriangleNum;
+
+ type=notextype;
+ color=0;
+
+ tfile=fopen( filename, "rb" );
+ // read model settings
+
+ fseek(tfile, 0, SEEK_SET);
+ funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+
+ // read the model data
+ /*if(owner)dealloc(owner);
+ if(possible)dealloc(possible);
+ if(vertex)dealloc(vertex);
+ if(normals)dealloc(normals);
+ if(facenormals)dealloc(facenormals);
+ if(Triangles)dealloc(Triangles);
+ if(vArray)dealloc(vArray);*/
+ deallocate();
+
+ numpossible=0;
+
+ owner = (int*)malloc(sizeof(int)*vertexNum);
+ possible = (int*)malloc(sizeof(int)*TriangleNum);
+ vertex = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle)*TriangleNum);
+ vArray = (GLfloat*)malloc(sizeof(GLfloat)*TriangleNum*24);
+
+ for(i=0;i<vertexNum;i++){
+ funpackf(tfile, "Bf Bf Bf", &vertex[i].x,&vertex[i].y,&vertex[i].z);
+ }
+
+ for(i=0;i<TriangleNum;i++){
+ // funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
+ short vertex[ 6];
+ funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
+ Triangles[i].vertex[ 0] = vertex[ 0];
+ Triangles[i].vertex[ 1] = vertex[ 2];
+ Triangles[i].vertex[ 2] = vertex[ 4];
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
+ }
+
+ fclose(tfile);
+
+ UpdateVertexArray();
+
+ for(i=0;i<vertexNum;i++){
+ owner[i]=-1;
+ }
+
+ static int j;
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+
+ return 1;
+}
+
+
+bool Model::load(char *filename,bool texture )
+{
+ FILE *tfile;
+ long i;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading model...") + filename);
+
+ if(visibleloading){
+ loadscreencolor=2;
+ pgame->LoadingScreen();
+ }
+
+ int oldvertexNum,oldTriangleNum;
+ oldvertexNum=vertexNum;
+ oldTriangleNum=TriangleNum;
+
+ type = normaltype;
+ color=0;
+
+ tfile=fopen( filename, "rb" );
+ // read model settings
+
+
+ fseek(tfile, 0, SEEK_SET);
+ funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+
+ // read the model data
+ /*if(owner)dealloc(owner);
+ if(possible)dealloc(possible);
+ if(vertex)dealloc(vertex);
+ if(normals)dealloc(normals);
+ if(facenormals)dealloc(facenormals);
+ if(Triangles)dealloc(Triangles);
+ if(vArray)dealloc(vArray);*/
+ deallocate();
+
+ numpossible=0;
+
+ owner = (int*)malloc(sizeof(int)*vertexNum);
+ possible = (int*)malloc(sizeof(int)*TriangleNum);
+ vertex = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ normals = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ facenormals = (XYZ*)malloc(sizeof(XYZ)*TriangleNum);
+ Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle)*TriangleNum);
+ vArray = (GLfloat*)malloc(sizeof(GLfloat)*TriangleNum*24);
+
+ for(i=0;i<vertexNum;i++){
+ funpackf(tfile, "Bf Bf Bf", &vertex[i].x,&vertex[i].y,&vertex[i].z);
+ }
+
+ for(i=0;i<TriangleNum;i++){
+ // funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
+ short vertex[ 6];
+ funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
+ Triangles[i].vertex[ 0] = vertex[ 0];
+ Triangles[i].vertex[ 1] = vertex[ 2];
+ Triangles[i].vertex[ 2] = vertex[ 4];
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
+ }
+
+ Texture.xsz=0;
+
+ fclose(tfile);
+
+ UpdateVertexArray();
+
+ for(i=0;i<vertexNum;i++){
+ owner[i]=-1;
+ }
+
+ static int j;
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+
+ return 1;
+}
+
+bool Model::loaddecal(char *filename,bool texture )
+{
+ FILE *tfile;
+ long i,j;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading decal...") + filename);
+
+ int oldvertexNum,oldTriangleNum;
+ oldvertexNum=vertexNum;
+ oldTriangleNum=TriangleNum;
+
+ type = decalstype;
+ numdecals=0;
+ color=0;
+
+ tfile=fopen( filename, "rb" );
+ // read model settings
+
+
+ fseek(tfile, 0, SEEK_SET);
+ funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+
+ // read the model data
+
+ /*if(owner)dealloc(owner);
+ if(possible)dealloc(possible);
+ if(vertex)dealloc(vertex);
+ if(normals)dealloc(normals);
+ if(facenormals)dealloc(facenormals);
+ if(Triangles)dealloc(Triangles);
+ if(vArray)dealloc(vArray);*/
+ deallocate();
+
+ numpossible=0;
+
+ owner = (int*)malloc(sizeof(int)*vertexNum);
+ possible = (int*)malloc(sizeof(int)*TriangleNum);
+ vertex = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ normals = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ facenormals = (XYZ*)malloc(sizeof(XYZ)*TriangleNum);
+ Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle)*TriangleNum);
+ vArray = (GLfloat*)malloc(sizeof(GLfloat)*TriangleNum*24);
+
+
+ for(i=0;i<vertexNum;i++){
+ funpackf(tfile, "Bf Bf Bf", &vertex[i].x,&vertex[i].y,&vertex[i].z);
+ }
+
+ for(i=0;i<TriangleNum;i++){
+ // funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
+ short vertex[ 6];
+ funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
+ Triangles[i].vertex[ 0] = vertex[ 0];
+ Triangles[i].vertex[ 1] = vertex[ 2];
+ Triangles[i].vertex[ 2] = vertex[ 4];
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
+ }
+
+
+ Texture.xsz=0;
+
+ fclose(tfile);
+
+ UpdateVertexArray();
+
+ for(i=0;i<vertexNum;i++){
+ owner[i]=-1;
+ }
+
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+
+ //allow decals
+ if(!decaltexcoords){
+ decaltexcoords = (float***)malloc(sizeof(float**)*max_model_decals);
+ for(i=0;i<max_model_decals;i++){
+ decaltexcoords[i] = (float**)malloc(sizeof(float*)*3);
+ for(j=0;j<3;j++){
+ decaltexcoords[i][j] = (float*)malloc(sizeof(float)*2);
+ }
+ }
+ //if(decalvertex)free(decalvertex);
+ decalvertex = (XYZ**)malloc(sizeof(XYZ*)*max_model_decals);
+ for(i=0;i<max_model_decals;i++){
+ decalvertex[i] = (XYZ*)malloc(sizeof(XYZ)*3);
+ }
+
+ decaltype = (int*)malloc(sizeof(int)*max_model_decals);
+ decalopacity = (float*)malloc(sizeof(float)*max_model_decals);
+ decalrotation = (float*)malloc(sizeof(float)*max_model_decals);
+ decalalivetime = (float*)malloc(sizeof(float)*max_model_decals);
+ decalposition = (XYZ*)malloc(sizeof(XYZ)*max_model_decals);
+ }
+
+ return 1;
+}
+
+bool Model::loadraw(char *filename )
+{
+ FILE *tfile;
+ long i;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading raw...") + filename);
+
+ int oldvertexNum,oldTriangleNum;
+ oldvertexNum=vertexNum;
+ oldTriangleNum=TriangleNum;
+
+ type = rawtype;
+ color=0;
+
+ tfile=fopen( filename, "rb" );
+ // read model settings
+
+
+ fseek(tfile, 0, SEEK_SET);
+ funpackf(tfile, "Bs Bs", &vertexNum, &TriangleNum);
+
+ // read the model data
+ /*if(owner)dealloc(owner);
+ if(possible)dealloc(possible);
+ if(vertex)dealloc(vertex);
+ if(normals)dealloc(normals);
+ if(facenormals)dealloc(facenormals);
+ if(Triangles)dealloc(Triangles);
+ if(vArray)dealloc(vArray);*/
+ deallocate();
+
+ numpossible=0;
+
+ owner = (int*)malloc(sizeof(int)*vertexNum);
+ possible = (int*)malloc(sizeof(int)*TriangleNum);
+ vertex = (XYZ*)malloc(sizeof(XYZ)*vertexNum);
+ Triangles = (TexturedTriangle*)malloc(sizeof(TexturedTriangle)*TriangleNum);
+ vArray = (GLfloat*)malloc(sizeof(GLfloat)*TriangleNum*24);
+
+
+ for(i=0;i<vertexNum;i++){
+ funpackf(tfile, "Bf Bf Bf", &vertex[i].x,&vertex[i].y,&vertex[i].z);
+ }
+
+ for(i=0;i<TriangleNum;i++){
+ // funpackf(tfile, "Bi Bi Bi", &Triangles[i].vertex[0], &Triangles[i].vertex[1], &Triangles[i].vertex[2]);
+ short vertex[ 6];
+ funpackf(tfile, "Bs Bs Bs Bs Bs Bs", &vertex[ 0], &vertex[ 1], &vertex[ 2], &vertex[ 3], &vertex[ 4], &vertex[ 5]);
+ Triangles[i].vertex[ 0] = vertex[ 0];
+ Triangles[i].vertex[ 1] = vertex[ 2];
+ Triangles[i].vertex[ 2] = vertex[ 4];
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gx[0], &Triangles[i].gx[1], &Triangles[i].gx[2]);
+ funpackf(tfile, "Bf Bf Bf", &Triangles[i].gy[0], &Triangles[i].gy[1], &Triangles[i].gy[2]);
+ }
+
+
+ fclose(tfile);
+
+ for(i=0;i<vertexNum;i++){
+ owner[i]=-1;
+ }
+
+ return 1;
+}
+
+
+void Model::UniformTexCoords()
+{
+ static int i;
+ for(i=0; i<TriangleNum; i++){
+ Triangles[i].gy[0]=vertex[Triangles[i].vertex[0]].y;
+ Triangles[i].gy[1]=vertex[Triangles[i].vertex[1]].y;
+ Triangles[i].gy[2]=vertex[Triangles[i].vertex[2]].y;
+ Triangles[i].gx[0]=vertex[Triangles[i].vertex[0]].x;
+ Triangles[i].gx[1]=vertex[Triangles[i].vertex[1]].x;
+ Triangles[i].gx[2]=vertex[Triangles[i].vertex[2]].x;
+ }
+ UpdateVertexArray();
+}
+
+
+void Model::FlipTexCoords()
+{
+ static int i;
+ for(i=0; i<TriangleNum; i++){
+ Triangles[i].gy[0]=-Triangles[i].gy[0];
+ Triangles[i].gy[1]=-Triangles[i].gy[1];
+ Triangles[i].gy[2]=-Triangles[i].gy[2];
+ }
+ UpdateVertexArray();
+}
+
+void Model::ScaleTexCoords(float howmuch)
+{
+ static int i;
+ for(i=0; i<TriangleNum; i++){
+ Triangles[i].gx[0]*=howmuch;
+ Triangles[i].gx[1]*=howmuch;
+ Triangles[i].gx[2]*=howmuch;
+ Triangles[i].gy[0]*=howmuch;
+ Triangles[i].gy[1]*=howmuch;
+ Triangles[i].gy[2]*=howmuch;
+ }
+ UpdateVertexArray();
+}
+
+void Model::Scale(float xscale,float yscale,float zscale)
+{
+ static int i;
+ for(i=0; i<vertexNum; i++){
+ vertex[i].x*=xscale;
+ vertex[i].y*=yscale;
+ vertex[i].z*=zscale;
+ }
+ UpdateVertexArray();
+
+ static int j;
+
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+}
+
+void Model::ScaleNormals(float xscale,float yscale,float zscale)
+{
+ if(type!=normaltype&&type!=decalstype)return;
+ static int i;
+ for(i=0; i<vertexNum; i++){
+ normals[i].x*=xscale;
+ normals[i].y*=yscale;
+ normals[i].z*=zscale;
+ }
+ for(i=0; i<TriangleNum; i++){
+ facenormals[i].x*=xscale;
+ facenormals[i].y*=yscale;
+ facenormals[i].z*=zscale;
+ }
+ UpdateVertexArray();
+}
+
+void Model::Translate(float xtrans,float ytrans,float ztrans)
+{
+ static int i;
+ for(i=0; i<vertexNum; i++){
+ vertex[i].x+=xtrans;
+ vertex[i].y+=ytrans;
+ vertex[i].z+=ztrans;
+ }
+ UpdateVertexArray();
+
+ static int j;
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+}
+
+void Model::Rotate(float xang,float yang,float zang)
+{
+ static int i;
+ for(i=0; i<vertexNum; i++){
+ vertex[i]=DoRotation(vertex[i],xang,yang,zang);
+ }
+ UpdateVertexArray();
+
+ static int j;
+ boundingsphereradius=0;
+ for(i=0;i<vertexNum;i++){
+ for(j=0;j<vertexNum;j++){
+ if(j!=i&&findDistancefast(&vertex[j],&vertex[i])/2>boundingsphereradius){
+ boundingsphereradius=findDistancefast(&vertex[j],&vertex[i])/2;
+ boundingspherecenter=(vertex[i]+vertex[j])/2;
+ }
+ }
+ }
+ boundingsphereradius=fast_sqrt(boundingsphereradius);
+}
+
+
+void Model::CalculateNormals(bool facenormalise)
+{
+ if(visibleloading){
+ loadscreencolor=3;
+ pgame->LoadingScreen();
+ }
+ static int i;
+ if(type!=normaltype&&type!=decalstype)return;
+
+ for(i=0; i<vertexNum; i++){
+ normals[i].x=0;
+ normals[i].y=0;
+ normals[i].z=0;
+ }
+
+ for(i=0;i<TriangleNum;i++){
+ CrossProduct(vertex[Triangles[i].vertex[1]]-vertex[Triangles[i].vertex[0]],vertex[Triangles[i].vertex[2]]-vertex[Triangles[i].vertex[0]],&facenormals[i]);
+
+ normals[Triangles[i].vertex[0]].x+=facenormals[i].x;
+ normals[Triangles[i].vertex[0]].y+=facenormals[i].y;
+ normals[Triangles[i].vertex[0]].z+=facenormals[i].z;
+
+ normals[Triangles[i].vertex[1]].x+=facenormals[i].x;
+ normals[Triangles[i].vertex[1]].y+=facenormals[i].y;
+ normals[Triangles[i].vertex[1]].z+=facenormals[i].z;
+
+ normals[Triangles[i].vertex[2]].x+=facenormals[i].x;
+ normals[Triangles[i].vertex[2]].y+=facenormals[i].y;
+ normals[Triangles[i].vertex[2]].z+=facenormals[i].z;
+ if(facenormalise)Normalise(&facenormals[i]);
+ }
+ for(i=0; i<vertexNum; i++){
+ Normalise(&normals[i]);
+ normals[i]*=-1;
+ }
+ UpdateVertexArrayNoTex();
+}
+
+void Model::drawimmediate()
+{
+ glBindTexture(GL_TEXTURE_2D,(unsigned long)textureptr);
+ glBegin(GL_TRIANGLES);
+ for(int i=0;i<TriangleNum;i++){
+ /*if(Triangles[i].vertex[0]<vertexNum&&Triangles[i].vertex[1]<vertexNum&&Triangles[i].vertex[2]<vertexNum&&Triangles[i].vertex[0]>=0&&Triangles[i].vertex[1]>=0&&Triangles[i].vertex[2]>=0){
+ if(isnormal(vertex[Triangles[i].vertex[0]].x)&&isnormal(vertex[Triangles[i].vertex[0]].y)&&isnormal(vertex[Triangles[i].vertex[0]].z)
+ &&isnormal(vertex[Triangles[i].vertex[1]].x)&&isnormal(vertex[Triangles[i].vertex[1]].y)&&isnormal(vertex[Triangles[i].vertex[1]].z)
+ &&isnormal(vertex[Triangles[i].vertex[2]].x)&&isnormal(vertex[Triangles[i].vertex[2]].y)&&isnormal(vertex[Triangles[i].vertex[2]].z)){
+ */
+ glTexCoord2f(Triangles[i].gx[0],Triangles[i].gy[0]);
+ if(color)glColor3f(normals[Triangles[i].vertex[0]].x,normals[Triangles[i].vertex[0]].y,normals[Triangles[i].vertex[0]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[0]].x,normals[Triangles[i].vertex[0]].y,normals[Triangles[i].vertex[0]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[0]].x,vertex[Triangles[i].vertex[0]].y,vertex[Triangles[i].vertex[0]].z);
+
+ glTexCoord2f(Triangles[i].gx[1],Triangles[i].gy[1]);
+ if(color)glColor3f(normals[Triangles[i].vertex[1]].x,normals[Triangles[i].vertex[1]].y,normals[Triangles[i].vertex[1]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[1]].x,normals[Triangles[i].vertex[1]].y,normals[Triangles[i].vertex[1]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[1]].x,vertex[Triangles[i].vertex[1]].y,vertex[Triangles[i].vertex[1]].z);
+
+ glTexCoord2f(Triangles[i].gx[2],Triangles[i].gy[2]);
+ if(color)glColor3f(normals[Triangles[i].vertex[2]].x,normals[Triangles[i].vertex[2]].y,normals[Triangles[i].vertex[2]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[2]].x,normals[Triangles[i].vertex[2]].y,normals[Triangles[i].vertex[2]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[2]].x,vertex[Triangles[i].vertex[2]].y,vertex[Triangles[i].vertex[2]].z);
+ //}
+ //}
+ }
+ glEnd();
+}
+
+void Model::draw()
+{
+ if(type!=normaltype&&type!=decalstype)return;
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ if(!color)glInterleavedArrays( GL_T2F_N3F_V3F,8*sizeof(GLfloat),&vArray[0]);
+ if(color)glInterleavedArrays( GL_T2F_C3F_V3F,8*sizeof(GLfloat),&vArray[0]);
+ glBindTexture(GL_TEXTURE_2D,(unsigned long)textureptr);
+
+#ifndef WIN32
+ glLockArraysEXT( 0, TriangleNum*3);
+#endif
+ glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+#ifndef WIN32
+ glUnlockArraysEXT();
+#endif
+
+
+ if(!color)glDisableClientState(GL_NORMAL_ARRAY);
+ if(color)glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ //drawimmediate();
+}
+
+void Model::drawdifftex(GLuint texture)
+{
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ if(!color)glInterleavedArrays( GL_T2F_N3F_V3F,8*sizeof(GLfloat),&vArray[0]);
+ if(color)glInterleavedArrays( GL_T2F_C3F_V3F,8*sizeof(GLfloat),&vArray[0]);
+
+ glBindTexture(GL_TEXTURE_2D,(unsigned long)texture);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+
+
+#ifndef WIN32
+ glLockArraysEXT( 0, TriangleNum*3);
+#endif
+ glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
+#ifndef WIN32
+ glUnlockArraysEXT();
+#endif
+
+
+ if(!color)glDisableClientState(GL_NORMAL_ARRAY);
+ if(color)glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ //drawdiffteximmediate(texture);
+}
+
+void Model::drawdiffteximmediate(GLuint texture)
+{
+ glBindTexture(GL_TEXTURE_2D,(unsigned long)texture);
+
+ glBegin(GL_TRIANGLES);
+ for(int i=0;i<TriangleNum;i++){
+ /*if(Triangles[i].vertex[0]<vertexNum&&Triangles[i].vertex[1]<vertexNum&&Triangles[i].vertex[2]<vertexNum&&Triangles[i].vertex[0]>=0&&Triangles[i].vertex[1]>=0&&Triangles[i].vertex[2]>=0){
+ if(isnormal(vertex[Triangles[i].vertex[0]].x)&&isnormal(vertex[Triangles[i].vertex[0]].y)&&isnormal(vertex[Triangles[i].vertex[0]].z)
+ &&isnormal(vertex[Triangles[i].vertex[1]].x)&&isnormal(vertex[Triangles[i].vertex[1]].y)&&isnormal(vertex[Triangles[i].vertex[1]].z)
+ &&isnormal(vertex[Triangles[i].vertex[2]].x)&&isnormal(vertex[Triangles[i].vertex[2]].y)&&isnormal(vertex[Triangles[i].vertex[2]].z)){
+ */glTexCoord2f(Triangles[i].gx[0],Triangles[i].gy[0]);
+ if(color)glColor3f(normals[Triangles[i].vertex[0]].x,normals[Triangles[i].vertex[0]].y,normals[Triangles[i].vertex[0]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[0]].x,normals[Triangles[i].vertex[0]].y,normals[Triangles[i].vertex[0]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[0]].x,vertex[Triangles[i].vertex[0]].y,vertex[Triangles[i].vertex[0]].z);
+
+ glTexCoord2f(Triangles[i].gx[1],Triangles[i].gy[1]);
+ if(color)glColor3f(normals[Triangles[i].vertex[1]].x,normals[Triangles[i].vertex[1]].y,normals[Triangles[i].vertex[1]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[1]].x,normals[Triangles[i].vertex[1]].y,normals[Triangles[i].vertex[1]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[1]].x,vertex[Triangles[i].vertex[1]].y,vertex[Triangles[i].vertex[1]].z);
+
+ glTexCoord2f(Triangles[i].gx[2],Triangles[i].gy[2]);
+ if(color)glColor3f(normals[Triangles[i].vertex[2]].x,normals[Triangles[i].vertex[2]].y,normals[Triangles[i].vertex[2]].z);
+ if(!color&&!flat)glNormal3f(normals[Triangles[i].vertex[2]].x,normals[Triangles[i].vertex[2]].y,normals[Triangles[i].vertex[2]].z);
+ if(!color&&flat)glNormal3f(facenormals[i].x,facenormals[i].y,facenormals[i].y);
+ glVertex3f(vertex[Triangles[i].vertex[2]].x,vertex[Triangles[i].vertex[2]].y,vertex[Triangles[i].vertex[2]].z);
+ //}
+ //}
+ }
+ glEnd();
+}
+
+void Model::drawdecals(GLuint shadowtexture,GLuint bloodtexture,GLuint bloodtexture2,GLuint breaktexture)
+{
+ if(decals){
+ if(type!=decalstype)return;
+ static int i,j;
+ static float distancemult;
+ static int lasttype;
+ static float viewdistsquared;
+ static bool blend;
+
+ viewdistsquared=viewdistance*viewdistance;
+ blend=1;
+
+ lasttype=-1;
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(0);
+ if(numdecals>max_model_decals)numdecals=max_model_decals;
+ for(i=0;i<numdecals;i++){
+ if(decaltype[i]==blooddecalfast&&decalalivetime[i]<2)decalalivetime[i]=2;
+
+ if(decaltype[i]==shadowdecal&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, shadowtexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(decaltype[i]==breakdecal&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, breaktexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalslow)&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, bloodtexture);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.15);
+ glBlendFunc(GL_ONE,GL_ZERO);
+ }
+ }
+ if((decaltype[i]==blooddecalfast)&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, bloodtexture2);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.15);
+ glBlendFunc(GL_ONE,GL_ZERO);
+ }
+ }
+ if(decaltype[i]==shadowdecal){
+ glColor4f(1,1,1,decalopacity[i]);
+ }
+ if(decaltype[i]==breakdecal){
+ glColor4f(1,1,1,decalopacity[i]);
+ if(decalalivetime[i]>58)glColor4f(1,1,1,decalopacity[i]*(60-decalalivetime[i])/2);
+ }
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)){
+ glColor4f(1,1,1,decalopacity[i]);
+ if(decalalivetime[i]<4)glColor4f(1,1,1,decalopacity[i]*decalalivetime[i]*.25);
+ if(decalalivetime[i]>58)glColor4f(1,1,1,decalopacity[i]*(60-decalalivetime[i])/2);
+ }
+ lasttype=decaltype[i];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_TRIANGLES);
+ for(int j=0;j<3;j++)
+ {
+ glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]); glVertex3f(decalvertex[i][j].x,decalvertex[i][j].y,decalvertex[i][j].z);
+ }
+ glEnd();
+ glPopMatrix();
+ }
+ for(i=numdecals-1;i>=0;i--){
+ decalalivetime[i]+=multiplier;
+ if(decaltype[i]==blooddecalslow)decalalivetime[i]-=multiplier*2/3;
+ if(decaltype[i]==blooddecalfast)decalalivetime[i]+=multiplier*4;
+ if(decaltype[i]==shadowdecal)DeleteDecal(i);
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)&&decalalivetime[i]>=60)DeleteDecal(i);
+ }
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+}
+
+void Model::DeleteDecal(int which)
+{
+ if(decals){
+ if(type!=decalstype)return;
+ decaltype[which]=decaltype[numdecals-1];
+ decalposition[which]=decalposition[numdecals-1];
+ for(int i=0;i<3;i++){
+ decalvertex[which][i]=decalvertex[numdecals-1][i];
+ decaltexcoords[which][i][0]=decaltexcoords[numdecals-1][i][0];
+ decaltexcoords[which][i][1]=decaltexcoords[numdecals-1][i][1];
+ }
+ decalrotation[which]=decalrotation[numdecals-1];
+ decalalivetime[which]=decalalivetime[numdecals-1];
+ decalopacity[which]=decalopacity[numdecals-1];
+ numdecals--;
+ }
+}
+
+void Model::MakeDecal(int atype, XYZ *where,float *size, float *opacity, float *rotation){
+ if(decals){
+ if(type!=decalstype)return;
+
+ static float placex,placez;
+ static XYZ rot;
+ //static XYZ point,point1,point2;
+ static float distance;
+ static int i,j;
+
+ if(*opacity>0)
+ if(findDistancefast(where,&boundingspherecenter)<(boundingsphereradius+*size)*(boundingsphereradius+*size))
+ for(i=0;i<TriangleNum;i++){
+ if(facenormals[i].y<-.1&&(vertex[Triangles[i].vertex[0]].y<where->y||vertex[Triangles[i].vertex[1]].y<where->y||vertex[Triangles[i].vertex[2]].y<where->y)){
+ decalposition[numdecals]=*where;
+ decaltype[numdecals]=atype;
+ decalrotation[numdecals]=*rotation;
+ decalalivetime[numdecals]=0;
+ distance=abs(((facenormals[i].x*where->x)+(facenormals[i].y*where->y)+(facenormals[i].z*where->z)-((facenormals[i].x*vertex[Triangles[i].vertex[0]].x)+(facenormals[i].y*vertex[Triangles[i].vertex[0]].y)+(facenormals[i].z*vertex[Triangles[i].vertex[0]].z)))/facenormals[i].y);
+ decalopacity[numdecals]=*opacity-distance/10;
+
+ if(decalopacity[numdecals>0]){
+ placex=vertex[Triangles[i].vertex[0]].x;
+ placez=vertex[Triangles[i].vertex[0]].z;
+
+ decaltexcoords[numdecals][0][0]=(placex-where->x)/(*size)/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where->z)/(*size)/2+.5;
+
+ decalvertex[numdecals][0].x=placex;
+ decalvertex[numdecals][0].z=placez;
+ decalvertex[numdecals][0].y=vertex[Triangles[i].vertex[0]].y;
+
+
+ placex=vertex[Triangles[i].vertex[1]].x;
+ placez=vertex[Triangles[i].vertex[1]].z;
+
+ decaltexcoords[numdecals][1][0]=(placex-where->x)/(*size)/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where->z)/(*size)/2+.5;
+
+ decalvertex[numdecals][1].x=placex;
+ decalvertex[numdecals][1].z=placez;
+ decalvertex[numdecals][1].y=vertex[Triangles[i].vertex[1]].y;
+
+
+ placex=vertex[Triangles[i].vertex[2]].x;
+ placez=vertex[Triangles[i].vertex[2]].z;
+
+ decaltexcoords[numdecals][2][0]=(placex-where->x)/(*size)/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where->z)/(*size)/2+.5;
+
+ decalvertex[numdecals][2].x=placex;
+ decalvertex[numdecals][2].z=placez;
+ decalvertex[numdecals][2].y=vertex[Triangles[i].vertex[2]].y;
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ {
+ if(decalrotation[numdecals]){
+ for(j=0;j<3;j++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][j][0]-.5;
+ rot.z=decaltexcoords[numdecals][j][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][j][0]=rot.x+.5;
+ decaltexcoords[numdecals][j][1]=rot.z+.5;
+ }
+ }
+ if(numdecals<max_model_decals-1)numdecals++;
+ }
+ }
+ }
+ }
+ }
+}
+
+void Model::MakeDecal(int atype, XYZ where,float size, float opacity, float rotation){
+ if(decals){
+ if(type!=decalstype)return;
+
+ static float placex,placez;
+ static XYZ rot;
+ //static XYZ point,point1,point2;
+ static float distance;
+ static int i,j;
+
+ if(opacity>0)
+ if(findDistancefast(&where,&boundingspherecenter)<(boundingsphereradius+size)*(boundingsphereradius+size))
+ for(i=0;i<TriangleNum;i++){
+ distance=abs(((facenormals[i].x*where.x)+(facenormals[i].y*where.y)+(facenormals[i].z*where.z)-((facenormals[i].x*vertex[Triangles[i].vertex[0]].x)+(facenormals[i].y*vertex[Triangles[i].vertex[0]].y)+(facenormals[i].z*vertex[Triangles[i].vertex[0]].z))));
+ if(distance<.02&&abs(facenormals[i].y)>abs(facenormals[i].x)&&abs(facenormals[i].y)>abs(facenormals[i].z)){
+ decalposition[numdecals]=where;
+ decaltype[numdecals]=atype;
+ decalrotation[numdecals]=rotation;
+ decalalivetime[numdecals]=0;
+ decalopacity[numdecals]=opacity-distance/10;
+
+ if(decalopacity[numdecals>0]){
+ placex=vertex[Triangles[i].vertex[0]].x;
+ placez=vertex[Triangles[i].vertex[0]].z;
+
+ decaltexcoords[numdecals][0][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][0].x=placex;
+ decalvertex[numdecals][0].z=placez;
+ decalvertex[numdecals][0].y=vertex[Triangles[i].vertex[0]].y;
+
+
+ placex=vertex[Triangles[i].vertex[1]].x;
+ placez=vertex[Triangles[i].vertex[1]].z;
+
+ decaltexcoords[numdecals][1][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][1].x=placex;
+ decalvertex[numdecals][1].z=placez;
+ decalvertex[numdecals][1].y=vertex[Triangles[i].vertex[1]].y;
+
+
+ placex=vertex[Triangles[i].vertex[2]].x;
+ placez=vertex[Triangles[i].vertex[2]].z;
+
+ decaltexcoords[numdecals][2][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][2].x=placex;
+ decalvertex[numdecals][2].z=placez;
+ decalvertex[numdecals][2].y=vertex[Triangles[i].vertex[2]].y;
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ {
+ if(decalrotation[numdecals]){
+ for(j=0;j<3;j++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][j][0]-.5;
+ rot.z=decaltexcoords[numdecals][j][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][j][0]=rot.x+.5;
+ decaltexcoords[numdecals][j][1]=rot.z+.5;
+ }
+ }
+ if(numdecals<max_model_decals-1)numdecals++;
+ }
+ }
+ }
+ else if(distance<.02&&abs(facenormals[i].x)>abs(facenormals[i].y)&&abs(facenormals[i].x)>abs(facenormals[i].z)){
+ decalposition[numdecals]=where;
+ decaltype[numdecals]=atype;
+ decalrotation[numdecals]=rotation;
+ decalalivetime[numdecals]=0;
+ decalopacity[numdecals]=opacity-distance/10;
+
+ if(decalopacity[numdecals>0]){
+ placex=vertex[Triangles[i].vertex[0]].y;
+ placez=vertex[Triangles[i].vertex[0]].z;
+
+ decaltexcoords[numdecals][0][0]=(placex-where.y)/(size)/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][0].x=vertex[Triangles[i].vertex[0]].x;
+ decalvertex[numdecals][0].z=placez;
+ decalvertex[numdecals][0].y=placex;
+
+
+ placex=vertex[Triangles[i].vertex[1]].y;
+ placez=vertex[Triangles[i].vertex[1]].z;
+
+ decaltexcoords[numdecals][1][0]=(placex-where.y)/(size)/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][1].x=vertex[Triangles[i].vertex[1]].x;
+ decalvertex[numdecals][1].z=placez;
+ decalvertex[numdecals][1].y=placex;
+
+
+ placex=vertex[Triangles[i].vertex[2]].y;
+ placez=vertex[Triangles[i].vertex[2]].z;
+
+ decaltexcoords[numdecals][2][0]=(placex-where.y)/(size)/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where.z)/(size)/2+.5;
+
+ decalvertex[numdecals][2].x=vertex[Triangles[i].vertex[2]].x;
+ decalvertex[numdecals][2].z=placez;
+ decalvertex[numdecals][2].y=placex;
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ {
+ if(decalrotation[numdecals]){
+ for(j=0;j<3;j++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][j][0]-.5;
+ rot.z=decaltexcoords[numdecals][j][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][j][0]=rot.x+.5;
+ decaltexcoords[numdecals][j][1]=rot.z+.5;
+ }
+ }
+ if(numdecals<max_model_decals-1)numdecals++;
+ }
+ }
+ }
+ else if(distance<.02&&abs(facenormals[i].z)>abs(facenormals[i].y)&&abs(facenormals[i].z)>abs(facenormals[i].x)){
+ decalposition[numdecals]=where;
+ decaltype[numdecals]=atype;
+ decalrotation[numdecals]=rotation;
+ decalalivetime[numdecals]=0;
+ decalopacity[numdecals]=opacity-distance/10;
+
+ if(decalopacity[numdecals>0]){
+ placex=vertex[Triangles[i].vertex[0]].x;
+ placez=vertex[Triangles[i].vertex[0]].y;
+
+ decaltexcoords[numdecals][0][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where.y)/(size)/2+.5;
+
+ decalvertex[numdecals][0].x=placex;
+ decalvertex[numdecals][0].z=vertex[Triangles[i].vertex[0]].z;
+ decalvertex[numdecals][0].y=placez;
+
+
+ placex=vertex[Triangles[i].vertex[1]].x;
+ placez=vertex[Triangles[i].vertex[1]].y;
+
+ decaltexcoords[numdecals][1][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where.y)/(size)/2+.5;
+
+ decalvertex[numdecals][1].x=placex;
+ decalvertex[numdecals][1].z=vertex[Triangles[i].vertex[1]].z;
+ decalvertex[numdecals][1].y=placez;
+
+
+ placex=vertex[Triangles[i].vertex[2]].x;
+ placez=vertex[Triangles[i].vertex[2]].y;
+
+ decaltexcoords[numdecals][2][0]=(placex-where.x)/(size)/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where.y)/(size)/2+.5;
+
+ decalvertex[numdecals][2].x=placex;
+ decalvertex[numdecals][2].z=vertex[Triangles[i].vertex[2]].z;
+ decalvertex[numdecals][2].y=placez;
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ {
+ if(decalrotation[numdecals]){
+ for(j=0;j<3;j++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][j][0]-.5;
+ rot.z=decaltexcoords[numdecals][j][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][j][0]=rot.x+.5;
+ decaltexcoords[numdecals][j][1]=rot.z+.5;
+ }
+ }
+ if(numdecals<max_model_decals-1)numdecals++;
+ }
+ }
+ }
+ }
+ }
+}
+
+Model::~Model()
+{
+ deallocate();
+
+ if(textureptr) glDeleteTextures( 1, &textureptr );
+}
+
+void Model::deallocate()
+{
+ int i = 0, j = 0;
+
+ if(owner)dealloc(owner);
+ owner = 0;
+
+ if(possible)dealloc(possible);
+ possible = 0;
+
+ if(vertex)dealloc(vertex);
+ vertex = 0;
+
+ if(normals)dealloc(normals);
+ normals = 0;
+
+ if(facenormals)dealloc(facenormals);
+ facenormals = 0;
+
+ if(Triangles)dealloc(Triangles);
+ Triangles = 0;
+
+ if(vArray)dealloc(vArray);
+ vArray = 0;
+
+
+ //allow decals
+ if(decaltexcoords)
+ {
+ for(i=0;i<max_model_decals;i++)
+ {
+ for(j=0;j<3;j++)
+ {
+ dealloc(decaltexcoords[i][j]);
+ }
+ dealloc(decaltexcoords[i]);
+ }
+ dealloc(decaltexcoords);
+ }
+ decaltexcoords = 0;
+
+
+ if (decalvertex)
+ {
+ for(i=0;i<max_model_decals;i++)
+ {
+ dealloc(decalvertex[i]);
+ }
+ dealloc(decalvertex);
+ }
+ decalvertex = 0;
+
+
+ dealloc(decaltype);
+ decaltype = 0;
+
+ dealloc(decalopacity);
+ decalopacity = 0;
+
+ dealloc(decalrotation);
+ decalrotation = 0;
+
+ dealloc(decalalivetime);
+ decalalivetime = 0;
+
+ dealloc(decalposition);
+ decalposition = 0;
+
+};
+
+Model::Model()
+{
+ vertexNum = 0,TriangleNum = 0;
+ hastexture = 0;
+
+ type = 0,oldtype = 0;
+
+ possible=0;
+ owner=0;
+ vertex=0;
+ normals=0;
+ facenormals=0;
+ Triangles=0;
+ vArray=0;
+
+ textureptr = 0;
+ memset(&Texture, 0, sizeof(Texture));
+ numpossible = 0;
+ color = 0;
+
+ boundingspherecenter = 0;
+ boundingsphereradius = 0;
+
+ decaltexcoords=0;
+ decalvertex=0;
+ decaltype=0;
+ decalopacity=0;
+ decalrotation=0;
+ decalalivetime=0;
+ decalposition=0;
+
+ numdecals = 0;
+
+ flat = 0;
+
+ type=nothing;
+}
--- /dev/null
+#ifndef _MODELS_H_
+#define _MODELS_H_
+
+/**> Model Loading <**/
+//
+// Model Maximums
+//
+#include "gl.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <vector>
+
+#include "Constants.h"
+#include "Terrain.h"
+#include "binio.h"
+#include "Quaternions.h"
+
+//
+// Textures List
+//
+typedef struct {
+ long xsz,ysz;
+ GLubyte *txt;
+} ModelTexture;
+
+//
+// Model Structures
+//
+
+class TexturedTriangle{
+public:
+ short vertex[3];
+ float gx[3],gy[3];
+};
+
+#define max_model_decals 300
+
+#define nothing 0
+#define normaltype 4
+#define notextype 1
+#define rawtype 2
+#define decalstype 3
+
+class Model{
+public:
+ short vertexNum,TriangleNum;
+ bool hastexture;
+
+ int type,oldtype;
+
+ int* possible;
+ int* owner;
+ XYZ* vertex;
+ XYZ* normals;
+ XYZ* facenormals;
+ TexturedTriangle* Triangles;
+ GLfloat* vArray;
+
+ /*int possible[max_model_vertex];
+ int owner[max_textured_triangle];
+ XYZ vertex[max_model_vertex];
+ XYZ normals[max_model_vertex];
+ XYZ facenormals[max_textured_triangle];
+ TexturedTriangle Triangles[max_textured_triangle];
+ GLfloat vArray[max_textured_triangle*24];*/
+
+ GLuint textureptr;
+ ModelTexture Texture;
+ int numpossible;
+ bool color;
+
+ XYZ boundingspherecenter;
+ float boundingsphereradius;
+
+ float*** decaltexcoords;
+ XYZ** decalvertex;
+ int* decaltype;
+ float* decalopacity;
+ float* decalrotation;
+ float* decalalivetime;
+ XYZ* decalposition;
+
+ /*float decaltexcoords[max_model_decals][3][2];
+ XYZ decalvertex[max_model_decals][3];
+ int decaltype[max_model_decals];
+ float decalopacity[max_model_decals];
+ float decalrotation[max_model_decals];
+ float decalalivetime[max_model_decals];
+ XYZ decalposition[max_model_decals];*/
+
+ int numdecals;
+
+ bool flat;
+
+ void DeleteDecal(int which);
+ void MakeDecal(int atype, XYZ *where, float *size, float *opacity, float *rotation);
+ void MakeDecal(int atype, XYZ where, float size, float opacity, float rotation);
+ void drawdecals(GLuint shadowtexture,GLuint bloodtexture,GLuint bloodtexture2,GLuint breaktexture);
+ int SphereCheck(XYZ *p1,float radius, XYZ *p, XYZ *move, float *rotate);
+ int SphereCheckPossible(XYZ *p1,float radius, XYZ *move, float *rotate);
+ int LineCheck(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate);
+ int LineCheckSlide(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate);
+ int LineCheckPossible(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate);
+ int LineCheckSlidePossible(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate);
+ void UpdateVertexArray();
+ void UpdateVertexArrayNoTex();
+ void UpdateVertexArrayNoTexNoNorm();
+ bool loadnotex(char *filename);
+ bool loadraw(char *filename);
+ bool load(char *filename,bool texture);
+ bool loaddecal(char *filename,bool texture);
+ void Scale(float xscale,float yscale,float zscale);
+ void FlipTexCoords();
+ void UniformTexCoords();
+ void ScaleTexCoords(float howmuch);
+ void ScaleNormals(float xscale,float yscale,float zscale);
+ void Translate(float xtrans,float ytrans,float ztrans);
+ void CalculateNormals(bool facenormalise);
+ void draw();
+ void drawdifftex(GLuint texture);
+ void drawimmediate();
+ void drawdiffteximmediate(GLuint texture);
+ void Rotate(float xang,float yang,float zang);
+ ~Model();
+ void deallocate();
+ Model();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ File: MoreFilesX.c
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+ Copyright: © 1992-2002 by Apple Computer, Inc., all rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ File Ownership:
+
+ DRI: Apple Macintosh Developer Technical Support
+
+ Other Contact: For bug reports, consult the following page on
+ the World Wide Web:
+ http://developer.apple.com/bugreporter/
+
+ Technology: DTS Sample Code
+
+ Writers:
+
+ (JL) Jim Luther
+
+ Change History (most recent first):
+
+ <4> 8/22/02 JL [3016251] Changed FSMoveRenameObjectUnicode to not use
+ the Temporary folder because it isn't available on
+ NFS volumes.
+ <3> 4/19/02 JL [2853905] Fixed #if test around header includes.
+ <2> 4/19/02 JL [2850624] Fixed C++ compile errors and Project Builder
+ warnings.
+ <2> 4/19/02 JL [2853901] Updated standard disclaimer.
+ <1> 1/25/02 JL MoreFilesX 1.0
+*/
+
+#if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #include <string.h>
+#else
+ #include <Carbon.h>
+ #include <string.h>
+#endif
+
+#include "MoreFilesX.h"
+
+/* Set BuildingMoreFilesXForMacOS9 to 1 if building for Mac OS 9 */
+#ifndef BuildingMoreFilesXForMacOS9
+ #define BuildingMoreFilesXForMacOS9 0
+#endif
+
+/*****************************************************************************/
+
+#pragma mark ----- Local type definitions -----
+
+struct FSIterateContainerGlobals
+{
+ IterateContainerFilterProcPtr iterateFilter; /* pointer to IterateFilterProc */
+ FSCatalogInfoBitmap whichInfo; /* fields of the CatalogInfo to get */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+ FSRef ref; /* FSRef */
+ FSSpec spec; /* FSSpec */
+ FSSpec *specPtr; /* pointer to spec field, or NULL */
+ HFSUniStr255 name; /* HFSUniStr255 */
+ HFSUniStr255 *namePtr; /* pointer to name field, or NULL */
+ void *yourDataPtr; /* a pointer to caller supplied data the filter may need to access */
+ ItemCount maxLevels; /* maximum levels to iterate through */
+ ItemCount currentLevel; /* the current level FSIterateContainerLevel is on */
+ Boolean quitFlag; /* set to true if filter wants to kill interation */
+ Boolean containerChanged; /* temporary - set to true if the current container changed during iteration */
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+};
+typedef struct FSIterateContainerGlobals FSIterateContainerGlobals;
+
+struct FSDeleteContainerGlobals
+{
+ OSErr result; /* result */
+ ItemCount actualObjects; /* number of objects returned */
+ FSCatalogInfo catalogInfo; /* FSCatalogInfo */
+};
+typedef struct FSDeleteContainerGlobals FSDeleteContainerGlobals;
+
+/*****************************************************************************/
+
+#pragma mark ----- Local prototypes -----
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals);
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals);
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName);
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize)
+{
+ OSErr srcResult;
+ OSErr dstResult;
+ OSErr result;
+ SInt64 forkSize;
+ ByteCount readActualCount;
+
+ /* check input parameters */
+ require_action((NULL != copyBufferPtr) && (0 != copyBufferSize), BadParameter, result = paramErr);
+
+ /* get source fork size */
+ result = FSGetForkSize(srcRefNum, &forkSize);
+ require_noerr(result, SourceFSGetForkSizeFailed);
+
+ /* allocate disk space for destination fork */
+ result = FSSetForkSize(dstRefNum, fsFromStart, forkSize);
+ require_noerr(result, DestinationFSSetForkSizeFailed);
+
+ /* reset source fork's position to 0 */
+ result = FSSetForkPosition(srcRefNum, fsFromStart, 0);
+ require_noerr(result, SourceFSSetForkPositionFailed);
+
+ /* reset destination fork's position to 0 */
+ result = FSSetForkPosition(dstRefNum, fsFromStart, 0);
+ require_noerr(result, DestinationFSSetForkPositionFailed);
+
+ /* If copyBufferSize is greater than 4K bytes, make it a multiple of 4k bytes */
+ /* This will make writes on local volumes faster */
+ if ( (copyBufferSize >= 0x00001000) && ((copyBufferSize & 0x00000fff) != 0) )
+ {
+ copyBufferSize &= ~(0x00001000 - 1);
+ }
+
+ /* copy source to destination */
+ srcResult = dstResult = noErr;
+ while ( (noErr == srcResult) && (noErr == dstResult) )
+ {
+ srcResult = FSReadFork(srcRefNum, fsAtMark + noCacheMask, 0, copyBufferSize, copyBufferPtr, &readActualCount);
+ dstResult = FSWriteFork(dstRefNum, fsAtMark + noCacheMask, 0, readActualCount, copyBufferPtr, NULL);
+ }
+
+ /* make sure there were no errors at the destination */
+ require_noerr_action(dstResult, DestinationFSWriteForkFailed, result = dstResult);
+
+ /* make sure the error at the source was eofErr */
+ require_action(eofErr == srcResult, SourceResultNotEofErr, result = srcResult);
+
+ /* everything went as expected */
+ result = noErr;
+
+SourceResultNotEofErr:
+DestinationFSWriteForkFailed:
+DestinationFSSetForkPositionFailed:
+SourceFSSetForkPositionFailed:
+DestinationFSSetForkSizeFailed:
+SourceFSGetForkSizeFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action((NULL != volParmsInfo) && (NULL != actualInfoSize),
+ BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
+ pb.ioParam.ioReqCount = (SInt32)bufferSize;
+ result = PBHGetVolParmsSync(&pb);
+ require_noerr(result, PBHGetVolParmsSync);
+
+ /* return number of bytes the file system returned in volParmsInfo buffer */
+ *actualInfoSize = (UInt32)pb.ioParam.ioActCount;
+
+PBHGetVolParmsSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != vRefNum, BadParameter, result = paramErr);
+
+ /* get the volume refNum from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return volume refNum from catalogInfo */
+ *vRefNum = catalogInfo.volume;
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ /* ask for the volume's sizes only if needed */
+ result = FSGetVolumeInfo(volume, 0, NULL,
+ (((NULL != freeBytes) || (NULL != totalBytes)) ? kFSVolInfoSizes : kFSVolInfoNone),
+ &info, volumeName, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != freeBytes )
+ {
+ *freeBytes = info.freeBytes;
+ }
+ if ( NULL != totalBytes )
+ {
+ *totalBytes = info.totalBytes;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature) /* can be NULL */
+{
+ OSErr result;
+ FSVolumeInfo info;
+
+ result = FSGetVolumeInfo(volume, 0, NULL, kFSVolInfoFSInfo, &info, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( NULL != fileSystemID )
+ {
+ *fileSystemID = info.filesystemID;
+ }
+ if ( NULL != signature )
+ {
+ *signature = info.signature;
+ }
+
+FSGetVolumeInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes)
+{
+ OSErr result;
+ OSErr memResult;
+ ItemCount volumeIndex;
+ FSRef ref;
+
+ /* check parameters */
+ require_action((NULL != volumeRefsHandle) && (NULL != numVolumes),
+ BadParameter, result = paramErr);
+
+ /* No volumes yet */
+ *numVolumes = 0;
+
+ /* Allocate a handle for the results */
+ *volumeRefsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *volumeRefsHandle, NewHandle, result = memFullErr);
+
+ /* Call FSGetVolumeInfo in loop to get all volumes starting with the first */
+ volumeIndex = 1;
+ do
+ {
+ result = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoNone, NULL, NULL, &ref);
+ if ( noErr == result )
+ {
+ /* concatenate the FSRef to the end of the handle */
+ PtrAndHand(&ref, (Handle)*volumeRefsHandle, sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ ++(*numVolumes); /* increment the volume count */
+ ++volumeIndex; /* and the volumeIndex to get the next volume*/
+ }
+ } while ( noErr == result );
+
+ /* nsvErr is OK -- it just means there are no more volumes */
+ require(nsvErr == result, FSGetVolumeInfo);
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetVolumeInfo:
+
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *volumeRefsHandle )
+ {
+ DisposeHandle((Handle)*volumeRefsHandle);
+ *volumeRefsHandle = NULL;
+ }
+ *numVolumes = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref)
+{
+ OSErr result;
+ FSRefParam pb;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ pb.ioVRefNum = volRefNum;
+ pb.ioDirID = dirID;
+ pb.ioNamePtr = (StringPtr)name;
+ pb.newRef = ref;
+ result = PBMakeFSRefSync(&pb);
+ require_noerr(result, PBMakeFSRefSync);
+
+PBMakeFSRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSMakePath(
+ SInt16 volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize)
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != path, BadParameter, result = paramErr);
+
+ /* convert the inputs to an FSRef */
+ result = FSMakeFSRef(volRefNum, dirID, name, &ref);
+ require_noerr(result, FSMakeFSRef);
+
+ /* and then convert the FSRef to a path */
+ result = FSRefMakePath(&ref, path, maxPathSize);
+ require_noerr(result, FSRefMakePath);
+
+FSRefMakePath:
+FSMakeFSRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, isDirectory);
+ require_noerr(result, FSPathMakeRef);
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+FSPathMakeRef:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName)
+{
+ OSStatus result;
+ ByteCount unicodeByteLength;
+ ByteCount unicodeBytesConverted;
+ ByteCount actualPascalBytes;
+ UnicodeMapping uMapping;
+ UnicodeToTextInfo utInfo;
+
+ /* check parameters */
+ require_action(NULL != hfsName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ hfsName[0] = 0;
+
+ unicodeByteLength = nameLength * sizeof(UniChar);
+ if ( 0 == unicodeByteLength )
+ {
+ /* do nothing */
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = (ScriptCode)GetScriptManagerVariable(smSysScript);
+ region = (RegionCode)GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint );
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint );
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateUnicodeToTextInfo(&uMapping, &utInfo);
+ require_noerr(result, CreateUnicodeToTextInfo);
+
+ result = ConvertFromUnicodeToText(utInfo, unicodeByteLength, name, kUnicodeLooseMappingsMask,
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ isVolumeName ? kHFSMaxVolumeNameChars : kHFSMaxFileNameChars,
+ &unicodeBytesConverted, &actualPascalBytes, &hfsName[1]);
+ require_noerr(result, ConvertFromUnicodeToText);
+
+ hfsName[0] = (unsigned char)actualPascalBytes; /* fill in length byte */
+
+ConvertFromUnicodeToText:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeUnicodeToTextInfo(&utInfo));
+ }
+
+CreateUnicodeToTextInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName)
+{
+ ByteCount unicodeByteLength;
+ OSStatus result;
+ UnicodeMapping uMapping;
+ TextToUnicodeInfo tuInfo;
+ ByteCount pascalCharsRead;
+
+ /* check parameters */
+ require_action(NULL != unicodeName, BadParameter, result = paramErr);
+
+ /* make sure output is valid in case we get errors or there's nothing to convert */
+ unicodeName->length = 0;
+
+ if ( 0 == StrLength(hfsName) )
+ {
+ result = noErr;
+ }
+ else
+ {
+ /* if textEncodingHint is kTextEncodingUnknown, get a "default" textEncodingHint */
+ if ( kTextEncodingUnknown == textEncodingHint )
+ {
+ ScriptCode script;
+ RegionCode region;
+
+ script = GetScriptManagerVariable(smSysScript);
+ region = GetScriptManagerVariable(smRegionCode);
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, region,
+ NULL, &textEncodingHint);
+ if ( paramErr == result )
+ {
+ /* ok, ignore the region and try again */
+ result = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
+ kTextRegionDontCare, NULL, &textEncodingHint);
+ }
+ if ( noErr != result )
+ {
+ /* ok... try something */
+ textEncodingHint = kTextEncodingMacRoman;
+ }
+ }
+
+ uMapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeV2_0,
+ kUnicodeCanonicalDecompVariant, kUnicode16BitFormat);
+ uMapping.otherEncoding = GetTextEncodingBase(textEncodingHint);
+ uMapping.mappingVersion = kUnicodeUseHFSPlusMapping;
+
+ result = CreateTextToUnicodeInfo(&uMapping, &tuInfo);
+ require_noerr(result, CreateTextToUnicodeInfo);
+
+ result = ConvertFromTextToUnicode(tuInfo, hfsName[0], &hfsName[1],
+ 0, /* no control flag bits */
+ 0, NULL, 0, NULL, /* offsetCounts & offsetArrays */
+ sizeof(unicodeName->unicode), /* output buffer size in bytes */
+ &pascalCharsRead, &unicodeByteLength, unicodeName->unicode);
+ require_noerr(result, ConvertFromTextToUnicode);
+
+ /* convert from byte count to char count */
+ unicodeName->length = unicodeByteLength / sizeof(UniChar);
+
+ConvertFromTextToUnicode:
+
+ /* verify the result in debug builds -- there's really not anything you can do if it fails */
+ verify_noerr(DisposeTextToUnicodeInfo(&tuInfo));
+ }
+
+CreateTextToUnicodeInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+Boolean FSRefValid(const FSRef *ref)
+{
+ return ( noErr == FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, NULL, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != parentRef, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeID, &catalogInfo, NULL, NULL, parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /*
+ * Note: FSRefs always point to real file system objects. So, there cannot
+ * be a FSRef to the parent of volume root directories. Early versions of
+ * Mac OS X do not handle this case correctly and incorrectly return a
+ * FSRef for the parent of volume root directories instead of returning an
+ * invalid FSRef (a cleared FSRef is invalid). The next three lines of code
+ * ensure that you won't run into this bug. WW9D!
+ */
+ if ( fsRtDirID == catalogInfo.nodeID )
+ {
+ /* clear parentRef and return noErr which is the proper behavior */
+ memset(parentRef, 0, sizeof(FSRef));
+ }
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName)
+{
+ OSErr result;
+
+ /* check parameters */
+ require_action(NULL != outName, BadParameter, result = paramErr);
+
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, outName, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != nodeID )
+ {
+ whichInfo |= kFSCatInfoNodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != nodeID )
+ {
+ *nodeID = catalogInfo.nodeID;
+ }
+ if ( NULL != isDirectory )
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information to get */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != userPrivileges )
+ {
+ whichInfo |= kFSCatInfoUserPrivs;
+ }
+ if ( NULL != permissions )
+ {
+ whichInfo |= kFSCatInfoPermissions;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ if ( NULL != userPrivileges )
+ {
+ *userPrivileges = catalogInfo.userPrivileges;
+ }
+ if ( NULL != permissions )
+ {
+ BlockMoveData(&catalogInfo.permissions, permissions, sizeof(UInt32) * 4);
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCheckLock(
+ const FSRef *ref)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSVolumeInfo volumeInfo;
+
+ /* get nodeFlags and vRefNum for container */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoVolume, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* is file locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ result = fLckdErr; /* file is locked */
+ }
+ else
+ {
+ /* file isn't locked, but is volume locked? */
+
+ /* get volume flags */
+ result = FSGetVolumeInfo(catalogInfo.volume, 0, NULL, kFSVolInfoFlags, &volumeInfo, NULL, NULL);
+ require_noerr(result, FSGetVolumeInfo);
+
+ if ( 0 != (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
+ {
+ result = wPrErr; /* volume locked by hardware */
+ }
+ else if ( 0 != (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) )
+ {
+ result = vLckdErr; /* volume locked by software */
+ }
+ }
+
+FSGetVolumeInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfoBitmap whichInfo;
+ FSCatalogInfo catalogInfo;
+
+ whichInfo = kFSCatInfoNodeFlags;
+ if ( NULL != dataLogicalSize )
+ {
+ /* get data fork size */
+ whichInfo |= kFSCatInfoDataSizes;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* get resource fork size */
+ whichInfo |= kFSCatInfoRsrcSizes;
+ }
+
+ /* get nodeFlags and catalog info */
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ if ( NULL != dataLogicalSize )
+ {
+ /* return data fork size */
+ *dataLogicalSize = catalogInfo.dataLogicalSize;
+ }
+ if ( NULL != rsrcLogicalSize )
+ {
+ /* return resource fork size */
+ *rsrcLogicalSize = catalogInfo.rsrcLogicalSize;
+ }
+
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount) /* can be NULL */
+{
+ OSErr result;
+ CatPositionRec forkIterator;
+ SInt64 forkSize;
+ SInt64 *forkSizePtr;
+ UInt64 forkPhysicalSize;
+ UInt64 *forkPhysicalSizePtr;
+
+ /* Determine if forkSize needed */
+ if ( NULL != totalLogicalSize)
+ {
+ *totalLogicalSize = 0;
+ forkSizePtr = &forkSize;
+ }
+ else
+ {
+ forkSizePtr = NULL;
+ }
+
+ /* Determine if forkPhysicalSize is needed */
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize = 0;
+ forkPhysicalSizePtr = &forkPhysicalSize;
+ }
+ else
+ {
+ forkPhysicalSizePtr = NULL;
+ }
+
+ /* zero fork count if returning it */
+ if ( NULL != forkCount )
+ {
+ *forkCount = 0;
+ }
+
+ /* Iterate through the forks to get the sizes */
+ forkIterator.initialize = 0;
+ do
+ {
+ result = FSIterateForks(ref, &forkIterator, NULL, forkSizePtr, forkPhysicalSizePtr);
+ if ( noErr == result )
+ {
+ if ( NULL != totalLogicalSize )
+ {
+ *totalLogicalSize += forkSize;
+ }
+
+ if ( NULL != totalPhysicalSize )
+ {
+ *totalPhysicalSize += forkPhysicalSize;
+ }
+
+ if ( NULL != forkCount )
+ {
+ ++*forkCount;
+ }
+ }
+ } while ( noErr == result );
+
+ /* any error result other than errFSNoMoreItems is serious */
+ require(errFSNoMoreItems == result, FSIterateForks);
+
+ /* Normal exit */
+ result = noErr;
+
+FSIterateForks:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSBumpDate(
+ const FSRef *ref)
+{
+ OSStatus result;
+ FSCatalogInfo catalogInfo;
+ UTCDateTime oldDateTime;
+#if !BuildingMoreFilesXForMacOS9
+ FSRef parentRef;
+ Boolean notifyParent;
+#endif
+
+#if !BuildingMoreFilesXForMacOS9
+ /* Get the node flags, the content modification date and time, and the parent ref */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoContentMod, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Notify the parent if this is a file */
+ notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
+#else
+ /* Get the content modification date and time */
+ result = FSGetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+#endif
+
+ oldDateTime = catalogInfo.contentModDate;
+
+ /* Get the current date and time */
+ result = GetUTCDateTime(&catalogInfo.contentModDate, kUTCDefaultOptions);
+ require_noerr(result, GetUTCDateTime);
+
+ /* if the old date and time is the the same as the current, bump the seconds by one */
+ if ( (catalogInfo.contentModDate.fraction == oldDateTime.fraction) &&
+ (catalogInfo.contentModDate.lowSeconds == oldDateTime.lowSeconds) &&
+ (catalogInfo.contentModDate.highSeconds == oldDateTime.highSeconds) )
+ {
+ ++catalogInfo.contentModDate.lowSeconds;
+ if ( 0 == catalogInfo.contentModDate.lowSeconds )
+ {
+ ++catalogInfo.contentModDate.highSeconds;
+ }
+ }
+
+ /* Bump the content modification date and time */
+ result = FSSetCatalogInfo(ref, kFSCatInfoContentMod, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+#if !BuildingMoreFilesXForMacOS9
+ /*
+ * The problem with FNNotify is that it is not available under Mac OS 9
+ * and there's no way to test for that except for looking for the symbol
+ * or something. So, I'll just conditionalize this for those who care
+ * to send a notification.
+ */
+
+ /* Send a notification for the parent of the file, or for the directory */
+ result = FNNotify(notifyParent ? &parentRef : ref, kFNDirectoryModifiedMessage, kNilOptions);
+ require_noerr(result, FNNotify);
+#endif
+
+ /* ignore errors from FSSetCatalogInfo (volume might be write protected) and FNNotify */
+FNNotify:
+FSSetCatalogInfo:
+
+ return ( noErr );
+
+ /**********************/
+
+GetUTCDateTime:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory) /* can be NULL */
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information is really needed */
+ whichInfo = kFSCatInfoNone;
+
+ if ( NULL != info )
+ {
+ /* get FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ }
+
+ if ( NULL != extendedInfo )
+ {
+ /* get ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ }
+
+ if ( NULL != isDirectory )
+ {
+ whichInfo |= kFSCatInfoNodeFlags;
+ }
+
+ result = FSGetCatalogInfo(ref, whichInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* return FinderInfo if requested */
+ if ( NULL != info )
+ {
+ BlockMoveData(catalogInfo.finderInfo, info, sizeof(FinderInfo));
+ }
+
+ /* return ExtendedFinderInfo if requested */
+ if ( NULL != extendedInfo)
+ {
+ BlockMoveData(catalogInfo.extFinderInfo, extendedInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ /* set isDirectory Boolean if requested */
+ if ( NULL != isDirectory)
+ {
+ *isDirectory = (0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags));
+ }
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info,
+ const ExtendedFinderInfo *extendedInfo)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSCatalogInfoBitmap whichInfo;
+
+ /* determine what catalog information will be set */
+ whichInfo = kFSCatInfoNone; /* start with none */
+ if ( NULL != info )
+ {
+ /* set FinderInfo */
+ whichInfo |= kFSCatInfoFinderInfo;
+ BlockMoveData(info, catalogInfo.finderInfo, sizeof(FinderInfo));
+ }
+ if ( NULL != extendedInfo )
+ {
+ /* set ExtendedFinderInfo */
+ whichInfo |= kFSCatInfoFinderXInfo;
+ BlockMoveData(extendedInfo, catalogInfo.extFinderInfo, sizeof(ExtendedFinderInfo));
+ }
+
+ result = FSSetCatalogInfo(ref, whichInfo, &catalogInfo);
+ require_noerr(result, FSGetCatalogInfo);
+
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get nodeFlags, finder info, and parent FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo, &catalogInfo , NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure FSRef was to a file */
+ require_action(0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), FSRefNotFile, result = notAFileErr);
+
+ /* If fileType not 0x00000000, change fileType */
+ if ( fileType != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileType = fileType;
+ }
+
+ /* If creator not 0x00000000, change creator */
+ if ( fileCreator != (OSType)0x00000000 )
+ {
+ ((FileInfo *)&catalogInfo.finderInfo)->fileCreator = fileCreator;
+ }
+
+ /* now, save the new information back to disk */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up */
+ /* the Finder to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSRefNotFile:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+ FSRef parentRef;
+
+ /* get the current finderInfo */
+ result = FSGetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, &parentRef);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set or clear the appropriate bits in the finderInfo.finderFlags */
+ if ( setBits )
+ {
+ /* OR in the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags |= flagBits;
+ }
+ else
+ {
+ /* AND out the bits */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~flagBits;
+ }
+
+ /* save the modified finderInfo */
+ result = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+ /* and attempt to bump the parent directory's mod date to wake up the Finder */
+ /* to the change we just made (ignore errors from this) */
+ verify_noerr(FSBumpDate(&parentRef));
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsInvisible) );
+}
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsInvisible) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kNameLocked) );
+}
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kNameLocked) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kIsStationery) );
+}
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kIsStationery) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, true, kHasCustomIcon) );
+}
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasCustomIcon) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref)
+{
+ return ( FSChangeFinderFlags(ref, false, kHasBeenInited) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get the source information */
+ result = FSGetCatalogInfo(sourceRef, kFSCatInfoSettableInfo, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* don't copy the hasBeenInited bit; clear it */
+ ((FileInfo *)&catalogInfo.finderInfo)->finderFlags &= ~kHasBeenInited;
+
+ /* should the locked bit be copied? */
+ if ( !copyLockBit )
+ {
+ /* no, make sure the locked bit is clear */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ }
+
+ /* set the destination information */
+ result = FSSetCatalogInfo(destinationRef, kFSCatInfoSettableInfo, &catalogInfo);
+ require_noerr(result, FSSetCatalogInfo);
+
+FSSetCatalogInfo:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* if function fails along the way, newRef is final location of file */
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ FSCatalogInfo catalogInfo;
+ FSRef originalDirectory;
+ TextEncoding originalTextEncodingHint;
+ HFSUniStr255 originalName;
+ HFSUniStr255 uniqueName; /* unique name given to object while moving it to destination */
+ long theSeed; /* the seed for generating unique names */
+
+ /* check parameters */
+ require_action(NULL != newRef, BadParameter, result = paramErr);
+
+ /* newRef = input to start with */
+ BlockMoveData(ref, newRef, sizeof(FSRef));
+
+ /* get destDirectory's vRefNum */
+ result = FSGetCatalogInfo(destDirectory, kFSCatInfoVolume, &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DestinationBad);
+
+ /* save vRefNum */
+ vRefNum = catalogInfo.volume;
+
+ /* get ref's vRefNum, TextEncoding, name and parent directory*/
+ result = FSGetCatalogInfo(ref, kFSCatInfoTextEncoding + kFSCatInfoVolume, &catalogInfo, &originalName, NULL, &originalDirectory);
+ require_noerr(result, SourceBad);
+
+ /* save TextEncoding */
+ originalTextEncodingHint = catalogInfo.textEncodingHint;
+
+ /* make sure ref and destDirectory are on same volume */
+ require_action(vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* Skip a few steps if we're not renaming */
+ if ( NULL != name )
+ {
+ /* generate a name that is unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &originalDirectory, destDirectory, &uniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStrFailed);
+
+ /* Rename the object to uniqueName */
+ result = FSRenameUnicode(ref, uniqueName.length, uniqueName.unicode, kTextEncodingUnknown, newRef);
+ require_noerr(result, FSRenameUnicodeBeforeMoveFailed);
+
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectAfterRenameFailed);
+
+ /* Rename the object to new name */
+ result = FSRenameUnicode(ref, nameLength, name, textEncodingHint, newRef);
+ require_noerr(result, FSRenameUnicodeAfterMoveFailed);
+ }
+ else
+ {
+ /* Move object to its new home */
+ result = FSMoveObject(newRef, destDirectory, newRef);
+ require_noerr(result, FSMoveObjectNoRenameFailed);
+ }
+
+ return ( result );
+
+ /*************/
+
+/*
+ * failure handling code when renaming
+ */
+
+FSRenameUnicodeAfterMoveFailed:
+
+ /* Error handling: move object back to original location - ignore errors */
+ verify_noerr(FSMoveObject(newRef, &originalDirectory, newRef));
+
+FSMoveObjectAfterRenameFailed:
+
+ /* Error handling: rename object back to original name - ignore errors */
+ verify_noerr(FSRenameUnicode(newRef, originalName.length, originalName.unicode, originalTextEncodingHint, newRef));
+
+FSRenameUnicodeBeforeMoveFailed:
+GenerateUniqueHFSUniStrFailed:
+
+/*
+ * failure handling code for renaming or not
+ */
+FSMoveObjectNoRenameFailed:
+NotSameVolume:
+SourceBad:
+DestinationBad:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSDeleteContainerLevel function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked
+ and then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerLevel quits and returns to the caller.
+
+ container --> FSRef to a directory.
+ theGlobals --> A pointer to a FSDeleteContainerGlobals struct
+ which contains the variables that do not need to
+ be allocated each time FSDeleteContainerLevel
+ recurses. That lets FSDeleteContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSDeleteContainerLevel(
+ const FSRef *container,
+ FSDeleteContainerGlobals *theGlobals)
+{
+ /* level locals */
+ FSIterator iterator;
+ FSRef itemToDelete;
+ UInt16 nodeFlags;
+
+ /* Open FSIterator for flat access and give delete optimization hint */
+ theGlobals->result = FSOpenIterator(container, kFSIterateFlat + kFSIterateDelete, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ /* delete the contents of the directory */
+ do
+ {
+ /* get 1 item to delete */
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ NULL, kFSCatInfoNodeFlags, &theGlobals->catalogInfo,
+ &itemToDelete, NULL, NULL);
+ if ( (noErr == theGlobals->result) && (1 == theGlobals->actualObjects) )
+ {
+ /* save node flags in local in case we have to recurse */
+ nodeFlags = theGlobals->catalogInfo.nodeFlags;
+
+ /* is it a file or directory? */
+ if ( 0 != (nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* it's a directory -- delete its contents before attempting to delete it */
+ FSDeleteContainerLevel(&itemToDelete, theGlobals);
+ }
+ /* are we still OK to delete? */
+ if ( noErr == theGlobals->result )
+ {
+ /* is item locked? */
+ if ( 0 != (nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock it (ignore result since FSDeleteObject will set it correctly) */
+ theGlobals->catalogInfo.nodeFlags = nodeFlags & ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(&itemToDelete, kFSCatInfoNodeFlags, &theGlobals->catalogInfo);
+ }
+ /* delete the item */
+ theGlobals->result = FSDeleteObject(&itemToDelete);
+ }
+ }
+ } while ( noErr == theGlobals->result );
+
+ /* we found the end of the items normally, so return noErr */
+ if ( errFSNoMoreItems == theGlobals->result )
+ {
+ theGlobals->result = noErr;
+ }
+
+ /* close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container)
+{
+ FSDeleteContainerGlobals theGlobals;
+
+ /* delete container's contents */
+ FSDeleteContainerLevel(container, &theGlobals);
+
+ return ( theGlobals.result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* get nodeFlags for container */
+ result = FSGetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL,NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* make sure container is a directory */
+ require_action(0 != (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), ContainerNotDirectory, result = dirNFErr);
+
+ /* delete container's contents */
+ result = FSDeleteContainerContents(container);
+ require_noerr(result, FSDeleteContainerContents);
+
+ /* is container locked? */
+ if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) )
+ {
+ /* then attempt to unlock container (ignore result since FSDeleteObject will set it correctly) */
+ catalogInfo.nodeFlags &= ~kFSNodeLockedMask;
+ (void) FSSetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo);
+ }
+
+ /* delete the container */
+ result = FSDeleteObject(container);
+
+FSDeleteContainerContents:
+ContainerNotDirectory:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The FSIterateContainerLevel function iterates the contents of a container
+ directory and calls a IterateContainerFilterProc function once for each
+ file and directory found.
+
+ theGlobals --> A pointer to a FSIterateContainerGlobals struct
+ which contains the variables needed globally by
+ all recusion levels of FSIterateContainerLevel.
+ That makes FSIterateContainer thread safe since
+ each call to it uses its own global world.
+ It also contains the variables that do not need
+ to be allocated each time FSIterateContainerLevel
+ recurses. That lets FSIterateContainerLevel use
+ less stack space per recursion level.
+*/
+
+static
+void
+FSIterateContainerLevel(
+ FSIterateContainerGlobals *theGlobals)
+{
+ FSIterator iterator;
+
+ /* If maxLevels is zero, we aren't checking levels */
+ /* If currentLevel < maxLevels, look at this level */
+ if ( (theGlobals->maxLevels == 0) ||
+ (theGlobals->currentLevel < theGlobals->maxLevels) )
+ {
+ /* Open FSIterator for flat access to theGlobals->ref */
+ theGlobals->result = FSOpenIterator(&theGlobals->ref, kFSIterateFlat, &iterator);
+ require_noerr(theGlobals->result, FSOpenIterator);
+
+ ++theGlobals->currentLevel; /* Go to next level */
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects,
+ &theGlobals->containerChanged, theGlobals->whichInfo, &theGlobals->catalogInfo,
+ &theGlobals->ref, theGlobals->specPtr, theGlobals->namePtr);
+ if ( (noErr == theGlobals->result || errFSNoMoreItems == theGlobals->result) &&
+ (0 != theGlobals->actualObjects) )
+ {
+ /* Call the IterateFilterProc */
+ theGlobals->quitFlag = CallIterateContainerFilterProc(theGlobals->iterateFilter,
+ theGlobals->containerChanged, theGlobals->currentLevel,
+ &theGlobals->catalogInfo, &theGlobals->ref,
+ theGlobals->specPtr, theGlobals->namePtr, theGlobals->yourDataPtr);
+ /* Is it a directory? */
+ if ( 0 != (theGlobals->catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) )
+ {
+ /* Keep going? */
+ if ( !theGlobals->quitFlag )
+ {
+ /* Dive again if the IterateFilterProc didn't say "quit" */
+ FSIterateContainerLevel(theGlobals);
+ }
+ }
+ }
+ /* time to fall back a level? */
+ } while ( (noErr == theGlobals->result) && (!theGlobals->quitFlag) );
+
+ /* errFSNoMoreItems is OK - it only means we hit the end of this level */
+ /* afpAccessDenied is OK, too - it only means we cannot see inside a directory */
+ if ( (errFSNoMoreItems == theGlobals->result) ||
+ (afpAccessDenied == theGlobals->result) )
+ {
+ theGlobals->result = noErr;
+ }
+
+ --theGlobals->currentLevel; /* Return to previous level as we leave */
+
+ /* Close the FSIterator (closing an open iterator should never fail) */
+ verify_noerr(FSCloseIterator(iterator));
+ }
+
+FSOpenIterator:
+
+ return;
+}
+
+/*****************************************************************************/
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr)
+{
+ OSErr result;
+ FSIterateContainerGlobals theGlobals;
+
+ /* make sure there is an iterateFilter */
+ require_action(iterateFilter != NULL, NoIterateFilter, result = paramErr);
+
+ /*
+ * set up the globals we need to access from the recursive routine
+ */
+ theGlobals.iterateFilter = iterateFilter;
+ /* we need the node flags no matter what was requested so we can detect files vs. directories */
+ theGlobals.whichInfo = whichInfo | kFSCatInfoNodeFlags;
+ /* start with input container -- the first OpenIterator will ensure it is a directory */
+ theGlobals.ref = *container;
+ if ( wantFSSpec )
+ {
+ theGlobals.specPtr = &theGlobals.spec;
+ }
+ else
+ {
+ theGlobals.specPtr = NULL;
+ }
+ if ( wantName )
+ {
+ theGlobals.namePtr = &theGlobals.name;
+ }
+ else
+ {
+ theGlobals.namePtr = NULL;
+ }
+ theGlobals.yourDataPtr = yourDataPtr;
+ theGlobals.maxLevels = maxLevels;
+ theGlobals.currentLevel = 0;
+ theGlobals.quitFlag = false;
+ theGlobals.containerChanged = false;
+ theGlobals.result = noErr;
+ theGlobals.actualObjects = 0;
+
+ /* here we go into recursion land... */
+ FSIterateContainerLevel(&theGlobals);
+ result = theGlobals.result;
+ require_noerr(result, FSIterateContainerLevel);
+
+FSIterateContainerLevel:
+NoIterateFilter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged)
+{
+ /* Grab items 10 at a time. */
+ enum { kMaxItemsPerBulkCall = 10 };
+
+ OSErr result;
+ OSErr memResult;
+ FSIterator iterator;
+ FSRef refs[kMaxItemsPerBulkCall];
+ ItemCount actualObjects;
+ Boolean changed;
+
+ /* check parameters */
+ require_action((NULL != refsHandle) && (NULL != numRefs) && (NULL != containerChanged),
+ BadParameter, result = paramErr);
+
+ *numRefs = 0;
+ *containerChanged = false;
+ *refsHandle = (FSRef **)NewHandle(0);
+ require_action(NULL != *refsHandle, NewHandle, result = memFullErr);
+
+ /* open an FSIterator */
+ result = FSOpenIterator(container, kFSIterateFlat, &iterator);
+ require_noerr(result, FSOpenIterator);
+
+ /* Call FSGetCatalogInfoBulk in loop to get all items in the container */
+ do
+ {
+ result = FSGetCatalogInfoBulk(iterator, kMaxItemsPerBulkCall, &actualObjects,
+ &changed, kFSCatInfoNone, NULL, refs, NULL, NULL);
+
+ /* if the container changed, set containerChanged for output, but keep going */
+ if ( changed )
+ {
+ *containerChanged = changed;
+ }
+
+ /* any result other than noErr and errFSNoMoreItems is serious */
+ require((noErr == result) || (errFSNoMoreItems == result), FSGetCatalogInfoBulk);
+
+ /* add objects to output array and count */
+ if ( 0 != actualObjects )
+ {
+ /* concatenate the FSRefs to the end of the handle */
+ PtrAndHand(refs, (Handle)*refsHandle, actualObjects * sizeof(FSRef));
+ memResult = MemError();
+ require_noerr_action(memResult, MemoryAllocationFailed, result = memResult);
+
+ *numRefs += actualObjects;
+ }
+ } while ( noErr == result );
+
+ verify_noerr(FSCloseIterator(iterator)); /* closing an open iterator should never fail, but... */
+
+ return ( noErr );
+
+ /**********************/
+
+MemoryAllocationFailed:
+FSGetCatalogInfoBulk:
+
+ /* close the iterator */
+ verify_noerr(FSCloseIterator(iterator));
+
+FSOpenIterator:
+ /* dispose of handle if already allocated and clear the outputs */
+ if ( NULL != *refsHandle )
+ {
+ DisposeHandle((Handle)*refsHandle);
+ *refsHandle = NULL;
+ }
+ *numRefs = 0;
+
+NewHandle:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+/*
+ The GenerateUniqueName function generates a HFSUniStr255 name that is
+ unique in both dir1 and dir2.
+
+ startSeed --> A pointer to a long which is used to generate the
+ unique name.
+ <-- It is modified on output to a value which should
+ be used to generate the next unique name.
+ dir1 --> The first directory.
+ dir2 --> The second directory.
+ uniqueName <-- A pointer to a HFSUniStr255 where the unique name
+ is to be returned.
+*/
+
+static
+OSErr
+GenerateUniqueHFSUniStr(
+ long *startSeed,
+ const FSRef *dir1,
+ const FSRef *dir2,
+ HFSUniStr255 *uniqueName)
+{
+ OSErr result;
+ long i;
+ FSRefParam pb;
+ FSRef newRef;
+ unsigned char hexStr[17] = "0123456789ABCDEF";
+
+ /* set up the parameter block */
+ pb.name = uniqueName->unicode;
+ pb.nameLength = 8; /* always 8 characters */
+ pb.textEncodingHint = kTextEncodingUnknown;
+ pb.newRef = &newRef;
+
+ /* loop until we get fnfErr with a filename in both directories */
+ result = noErr;
+ while ( fnfErr != result )
+ {
+ /* convert startSeed to 8 character Unicode string */
+ uniqueName->length = 8;
+ for ( i = 0; i < 8; ++i )
+ {
+ uniqueName->unicode[i] = hexStr[((*startSeed >> ((7-i)*4)) & 0xf)];
+ }
+
+ /* try in dir1 */
+ pb.ref = dir1;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr == result )
+ {
+ /* try in dir2 */
+ pb.ref = dir2;
+ result = PBMakeFSRefUnicodeSync(&pb);
+ if ( fnfErr != result )
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir2PBMakeFSRefUnicodeSyncFailed);
+ }
+ }
+ else
+ {
+ /* exit if anything other than noErr or fnfErr */
+ require_noerr(result, Dir1PBMakeFSRefUnicodeSyncFailed);
+ }
+
+ /* increment seed for next pass through loop, */
+ /* or for next call to GenerateUniqueHFSUniStr */
+ ++(*startSeed);
+ }
+
+ /* we have a unique file name which doesn't exist in dir1 or dir2 */
+ result = noErr;
+
+Dir2PBMakeFSRefUnicodeSyncFailed:
+Dir1PBMakeFSRefUnicodeSyncFailed:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef)
+{
+ enum
+ {
+ /* get all settable info except for mod dates, plus the volume refNum and parent directory ID */
+ kGetCatInformationMask = (kFSCatInfoSettableInfo |
+ kFSCatInfoVolume |
+ kFSCatInfoParentDirID) &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod),
+ /* set everything possible except for mod dates */
+ kSetCatinformationMask = kFSCatInfoSettableInfo &
+ ~(kFSCatInfoContentMod | kFSCatInfoAttrMod)
+ };
+
+ OSErr result;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+ FSCatalogInfo sourceCatalogInfo; /* source file's catalog information */
+ FSCatalogInfo destCatalogInfo; /* destination file's catalog information */
+ HFSUniStr255 sourceName; /* source file's Unicode name */
+ HFSUniStr255 destName; /* destination file's Unicode name */
+ FSRef sourceCurrentRef; /* FSRef to current location of source file throughout this function */
+ FSRef destCurrentRef; /* FSRef to current location of destination file throughout this function */
+ FSRef sourceParentRef; /* FSRef to parent directory of source file */
+ FSRef destParentRef; /* FSRef to parent directory of destination file */
+ HFSUniStr255 sourceUniqueName; /* unique name given to source file while exchanging it with destination */
+ HFSUniStr255 destUniqueName; /* unique name given to destination file while exchanging it with source */
+ long theSeed; /* the seed for generating unique names */
+ Boolean sameParentDirs; /* true if source and destinatin parent directory is the same */
+
+ /* check parameters */
+ require_action((NULL != newSourceRef) && (NULL != newDestRef), BadParameter, result = paramErr);
+
+ /* output refs and current refs = input refs to start with */
+ BlockMoveData(sourceRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(sourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ BlockMoveData(destRef, newDestRef, sizeof(FSRef));
+ BlockMoveData(destRef, &destCurrentRef, sizeof(FSRef));
+
+ /* get source volume's vRefNum */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kFSCatInfoVolume, &sourceCatalogInfo, NULL, NULL, NULL);
+ require_noerr(result, DetermineSourceVRefNumFailed);
+
+ /* see if that volume supports FSExchangeObjects */
+ result = FSGetVolParms(sourceCatalogInfo.volume, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ if ( (noErr == result) && VolSupportsFSExchangeObjects(&volParmsInfo) )
+ {
+ /* yes - use FSExchangeObjects */
+ result = FSExchangeObjects(sourceRef, destRef);
+ }
+ else
+ {
+ /* no - emulate FSExchangeObjects */
+
+ /* Note: The compatibility case won't work for files with *Btree control blocks. */
+ /* Right now the only *Btree files are created by the system. */
+
+ /* get all catalog information and Unicode names for each file */
+ result = FSGetCatalogInfo(&sourceCurrentRef, kGetCatInformationMask, &sourceCatalogInfo, &sourceName, NULL, &sourceParentRef);
+ require_noerr(result, SourceFSGetCatalogInfoFailed);
+
+ result = FSGetCatalogInfo(&destCurrentRef, kGetCatInformationMask, &destCatalogInfo, &destName, NULL, &destParentRef);
+ require_noerr(result, DestFSGetCatalogInfoFailed);
+
+ /* make sure source and destination are on same volume */
+ require_action(sourceCatalogInfo.volume == destCatalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* make sure both files are *really* files */
+ require_action((0 == (sourceCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) &&
+ (0 == (destCatalogInfo.nodeFlags & kFSNodeIsDirectoryMask)), NotAFile, result = notAFileErr);
+
+ /* generate 2 names that are unique in both directories */
+ theSeed = 0x4a696d4c; /* a fine unlikely filename */
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &sourceUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr1Failed);
+
+ result = GenerateUniqueHFSUniStr(&theSeed, &sourceParentRef, &destParentRef, &destUniqueName);
+ require_noerr(result, GenerateUniqueHFSUniStr2Failed);
+
+ /* rename sourceCurrentRef to sourceUniqueName */
+ result = FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef);
+ require_noerr(result, FSRenameUnicode1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename destCurrentRef to destUniqueName */
+ result = FSRenameUnicode(&destCurrentRef, destUniqueName.length, destUniqueName.unicode, kTextEncodingUnknown, newDestRef);
+ require_noerr(result, FSRenameUnicode2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+
+ /* are the source and destination parent directories the same? */
+ sameParentDirs = ( sourceCatalogInfo.parentDirID == destCatalogInfo.parentDirID );
+ if ( !sameParentDirs )
+ {
+ /* move source file to dest parent directory */
+ result = FSMoveObject(&sourceCurrentRef, &destParentRef, newSourceRef);
+ require_noerr(result, FSMoveObject1Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* move dest file to source parent directory */
+ result = FSMoveObject(&destCurrentRef, &sourceParentRef, newDestRef);
+ require_noerr(result, FSMoveObject2Failed);
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+
+ /* At this point, the files are in their new locations (if they were moved). */
+ /* The source file is named sourceUniqueName and is in the directory referred to */
+ /* by destParentRef. The destination file is named destUniqueName and is in the */
+ /* directory referred to by sourceParentRef. */
+
+ /* give source file the dest file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&sourceCurrentRef, kSetCatinformationMask, &destCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo1Failed);
+
+ /* give dest file the source file's catalog information except for mod dates */
+ result = FSSetCatalogInfo(&destCurrentRef, kSetCatinformationMask, &sourceCatalogInfo);
+ require_noerr(result, FSSetCatalogInfo2Failed);
+
+ /* rename source file with dest file's name */
+ result = FSRenameUnicode(&sourceCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newSourceRef);
+ require_noerr(result, FSRenameUnicode3Failed);
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+
+ /* rename dest file with source file's name */
+ result = FSRenameUnicode(&destCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newDestRef);
+ require_noerr(result, FSRenameUnicode4Failed);
+
+ /* we're done with no errors, so swap newSourceRef and newDestRef */
+ BlockMoveData(newDestRef, newSourceRef, sizeof(FSRef));
+ BlockMoveData(&sourceCurrentRef, newDestRef, sizeof(FSRef));
+ }
+
+ return ( result );
+
+ /**********************/
+
+/* If there are any failures while emulating FSExchangeObjects, attempt to reverse any steps */
+/* already taken. In any case, newSourceRef and newDestRef will refer to the files in whatever */
+/* state and location they ended up in so that both files can be found by the calling code. */
+
+FSRenameUnicode4Failed:
+
+ /* attempt to rename source file to sourceUniqueName */
+ if ( noErr == FSRenameUnicode(&sourceCurrentRef, sourceUniqueName.length, sourceUniqueName.unicode, kTextEncodingUnknown, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+
+FSRenameUnicode3Failed:
+
+ /* attempt to restore dest file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&destCurrentRef, kFSCatInfoSettableInfo, &destCatalogInfo));
+
+FSSetCatalogInfo2Failed:
+
+ /* attempt to restore source file's catalog information */
+ verify_noerr(FSSetCatalogInfo(&sourceCurrentRef, kFSCatInfoSettableInfo, &sourceCatalogInfo));
+
+FSSetCatalogInfo1Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move dest file back to dest directory */
+ if ( noErr == FSMoveObject(&destCurrentRef, &destParentRef, newDestRef) )
+ {
+ BlockMoveData(newDestRef, &destCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject2Failed:
+
+ if ( !sameParentDirs )
+ {
+ /* attempt to move source file back to source directory */
+ if ( noErr == FSMoveObject(&sourceCurrentRef, &sourceParentRef, newSourceRef) )
+ {
+ BlockMoveData(newSourceRef, &sourceCurrentRef, sizeof(FSRef));
+ }
+ }
+
+FSMoveObject1Failed:
+
+ /* attempt to rename dest file to original name */
+ verify_noerr(FSRenameUnicode(&destCurrentRef, destName.length, destName.unicode, destCatalogInfo.textEncodingHint, newDestRef));
+
+FSRenameUnicode2Failed:
+
+ /* attempt to rename source file to original name */
+ verify_noerr(FSRenameUnicode(&sourceCurrentRef, sourceName.length, sourceName.unicode, sourceCatalogInfo.textEncodingHint, newSourceRef));
+
+FSRenameUnicode1Failed:
+GenerateUniqueHFSUniStr2Failed:
+GenerateUniqueHFSUniStr1Failed:
+NotAFile:
+NotSameVolume:
+DestFSGetCatalogInfoFailed:
+SourceFSGetCatalogInfoFailed:
+DetermineSourceVRefNumFailed:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBLockRangeSync(&pb);
+ require_noerr(result, PBLockRangeSync);
+
+PBLockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ pb.ioParam.ioRefNum = refNum;
+ pb.ioParam.ioReqCount = rangeLength;
+ pb.ioParam.ioPosMode = fsFromStart;
+ pb.ioParam.ioPosOffset = rangeStart;
+ result = PBUnlockRangeSync(&pb);
+ require_noerr(result, PBUnlockRangeSync);
+
+PBUnlockRangeSync:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights) /* can be NULL */
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* get directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ result = PBHGetDirAccessSync(&pb);
+ require_noerr(result, PBHGetDirAccessSync);
+
+ /* return the IDs and access rights */
+ if ( NULL != ownerID )
+ {
+ *ownerID = pb.accessParam.ioACOwnerID;
+ }
+ if ( NULL != groupID )
+ {
+ *groupID = pb.accessParam.ioACGroupID;
+ }
+ if ( NULL != accessRights )
+ {
+ *accessRights = pb.accessParam.ioACAccess;
+ }
+
+PBHGetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights)
+{
+ OSErr result;
+ FSSpec spec;
+ HParamBlockRec pb;
+
+ enum
+ {
+ /* Just the bits that can be set */
+ kSetDirAccessSettableMask = (kioACAccessBlankAccessMask +
+ kioACAccessEveryoneWriteMask + kioACAccessEveryoneReadMask + kioACAccessEveryoneSearchMask +
+ kioACAccessGroupWriteMask + kioACAccessGroupReadMask + kioACAccessGroupSearchMask +
+ kioACAccessOwnerWriteMask + kioACAccessOwnerReadMask + kioACAccessOwnerSearchMask)
+ };
+
+ /* get FSSpec from FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* set directory access info for FSSpec */
+ pb.accessParam.ioNamePtr = (StringPtr)spec.name;
+ pb.accessParam.ioVRefNum = spec.vRefNum;
+ pb.fileParam.ioDirID = spec.parID;
+ pb.accessParam.ioACOwnerID = ownerID;
+ pb.accessParam.ioACGroupID = groupID;
+ pb.accessParam.ioACAccess = accessRights & kSetDirAccessSettableMask;
+ result = PBHSetDirAccessSync(&pb);
+ require_noerr(result, PBHSetDirAccessSync);
+
+PBHSetDirAccessSync:
+FSGetCatalogInfo:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != size, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)size;
+ result = PBGetVolMountInfoSize(&pb);
+ require_noerr(result, PBGetVolMountInfoSize);
+
+PBGetVolMountInfoSize:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volMountInfo, BadParameter, result = paramErr);
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBGetVolMountInfo(&pb);
+ require_noerr(result, PBGetVolMountInfo);
+
+PBGetVolMountInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum)
+{
+ OSErr result;
+ ParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != volRefNum, BadParameter, result = paramErr);
+
+ pb.ioParam.ioBuffer = (Ptr)volMountInfo;
+ result = PBVolumeMount(&pb);
+ require_noerr(result, PBVolumeMount);
+
+ /* return the volume reference number */
+ *volRefNum = pb.ioParam.ioVRefNum;
+
+PBVolumeMount:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != name, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = name;
+ pb.objParam.ioObjID = ugID;
+ result = PBHMapIDSync(&pb);
+ require_noerr(result, PBHMapIDSync);
+
+PBHMapIDSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID)
+{
+ OSErr result;
+ HParamBlockRec pb;
+
+ /* check parameters */
+ require_action(NULL != ugID, BadParameter, result = paramErr);
+
+ pb.objParam.ioNamePtr = NULL;
+ pb.objParam.ioVRefNum = volRefNum;
+ pb.objParam.ioObjType = objType;
+ pb.objParam.ioObjNamePtr = (StringPtr)name;
+ result = PBHMapNameSync(&pb);
+ require_noerr(result, PBHMapNameSync);
+
+ /* return the user or group ID */
+ *ugID = pb.objParam.ioObjID;
+
+PBHMapNameSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports CopyFile */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasCopyFile(&volParmsInfo),
+ NoCopyFileSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* tell the server to copy the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioDstVRefNum = catalogInfo.volume;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != copyName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, copyName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHCopyFileSync(&pb);
+ require_noerr(result, PBHCopyFileSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioDstVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHCopyFileSync:
+UnicodeNameGetHFSName:
+FSGetCatalogInfo_dstDirectoryRef:
+NoCopyFileSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef) /* can be NULL */
+{
+ OSErr result;
+ FSSpec srcFileSpec;
+ FSCatalogInfo catalogInfo;
+ HParamBlockRec pb;
+ Str31 hfsName;
+ GetVolParmsInfoBuffer volParmsInfo;
+ UInt32 infoSize;
+
+ /* get source FSSpec from source FSRef */
+ result = FSGetCatalogInfo(srcFileRef, kFSCatInfoNone, NULL, NULL, &srcFileSpec, NULL);
+ require_noerr(result, FSGetCatalogInfo_srcFileRef);
+
+ /* Make sure the volume supports MoveRename */
+ result = FSGetVolParms(srcFileSpec.vRefNum, sizeof(GetVolParmsInfoBuffer),
+ &volParmsInfo, &infoSize);
+ require_action((noErr == result) && VolHasMoveRename(&volParmsInfo),
+ NoMoveRenameSupport, result = paramErr);
+
+ /* get destination volume reference number and destination directory ID from destination FSRef */
+ result = FSGetCatalogInfo(dstDirectoryRef, kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo_dstDirectoryRef);
+
+ /* make sure the source and destination are on the same volume */
+ require_action(srcFileSpec.vRefNum == catalogInfo.volume, NotSameVolume, result = diffVolErr);
+
+ /* tell the server to move and rename the object */
+ pb.copyParam.ioVRefNum = srcFileSpec.vRefNum;
+ pb.copyParam.ioDirID = srcFileSpec.parID;
+ pb.copyParam.ioNamePtr = (StringPtr)srcFileSpec.name;
+ pb.copyParam.ioNewDirID = (long)catalogInfo.nodeID;
+ pb.copyParam.ioNewName = NULL;
+ if ( NULL != moveName )
+ {
+ result = UnicodeNameGetHFSName(nameLength, moveName, textEncodingHint, false, hfsName);
+ require_noerr(result, UnicodeNameGetHFSName);
+
+ pb.copyParam.ioCopyName = hfsName;
+ }
+ else
+ {
+ pb.copyParam.ioCopyName = NULL;
+ }
+ result = PBHMoveRenameSync(&pb);
+ require_noerr(result, PBHMoveRenameSync);
+
+ if ( NULL != newRef )
+ {
+ verify_noerr(FSMakeFSRef(pb.copyParam.ioVRefNum, pb.copyParam.ioNewDirID,
+ pb.copyParam.ioCopyName, newRef));
+ }
+
+PBHMoveRenameSync:
+UnicodeNameGetHFSName:
+NotSameVolume:
+FSGetCatalogInfo_dstDirectoryRef:
+NoMoveRenameSupport:
+FSGetCatalogInfo_srcFileRef:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref)
+{
+ OSErr result;
+ FIDParam pb;
+ Str255 tempStr;
+
+ /* check parameters */
+ require_action(NULL != ref, BadParameter, result = paramErr);
+
+ /* resolve the file ID reference */
+ tempStr[0] = 0;
+ pb.ioNamePtr = tempStr;
+ pb.ioVRefNum = volRefNum;
+ pb.ioFileID = fileID;
+ result = PBResolveFileIDRefSync((HParmBlkPtr)&pb);
+ require_noerr(result, PBResolveFileIDRefSync);
+
+ /* and then make an FSRef to the file */
+ result = FSMakeFSRef(volRefNum, pb.ioSrcDirID, tempStr, ref);
+ require_noerr(result, FSMakeFSRef);
+
+FSMakeFSRef:
+PBResolveFileIDRefSync:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID)
+{
+ OSErr result;
+ FSSpec spec;
+ FIDParam pb;
+
+ /* check parameters */
+ require_action(NULL != fileID, BadParameter, result = paramErr);
+
+ /* Get an FSSpec from the FSRef */
+ result = FSGetCatalogInfo(ref, kFSCatInfoNone, NULL, NULL, &spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Create (or get) the file ID reference using the FSSpec */
+ pb.ioNamePtr = (StringPtr)spec.name;
+ pb.ioVRefNum = spec.vRefNum;
+ pb.ioSrcDirID = spec.parID;
+ result = PBCreateFileIDRefSync((HParmBlkPtr)&pb);
+ require((noErr == result) || (fidExists == result) || (afpIDExists == result),
+ PBCreateFileIDRefSync);
+
+ /* return the file ID reference */
+ *fileID = pb.ioFileID;
+
+PBCreateFileIDRefSync:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize)
+{
+ enum
+ {
+ kSlopMemory = 0x00008000 /* 32K - Amount of free memory to leave when allocating buffers */
+ };
+
+ Ptr tempPtr;
+
+ /* check parameters */
+ require_action(NULL != buffActSize, BadParameter, tempPtr = NULL);
+
+ /* Make request a multiple of 4K bytes */
+ buffReqSize = buffReqSize & 0xfffff000;
+
+ if ( buffReqSize < 0x00001000 )
+ {
+ /* Request was smaller than 4K bytes - make it 4K */
+ buffReqSize = 0x00001000;
+ }
+
+ /* Attempt to allocate the memory */
+ tempPtr = NewPtr(buffReqSize);
+
+ /* If request failed, go to backup plan */
+ if ( (tempPtr == NULL) && (buffReqSize > 0x00001000) )
+ {
+ /*
+ ** Try to get largest 4K byte block available
+ ** leaving some slop for the toolbox if possible
+ */
+ long freeMemory = (FreeMem() - kSlopMemory) & 0xfffff000;
+
+ buffReqSize = MaxBlock() & 0xfffff000;
+
+ if ( buffReqSize > freeMemory )
+ {
+ buffReqSize = freeMemory;
+ }
+
+ if ( buffReqSize == 0 )
+ {
+ buffReqSize = 0x00001000;
+ }
+
+ tempPtr = NewPtr(buffReqSize);
+ }
+
+ /* Return bytes allocated */
+ if ( tempPtr != NULL )
+ {
+ *buffActSize = buffReqSize;
+ }
+ else
+ {
+ *buffActSize = 0;
+ }
+
+BadParameter:
+
+ return ( tempPtr );
+}
+
+/*****************************************************************************/
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref)
+{
+ return ( FSGetForkCBInfo(refNum, 0, NULL, NULL, NULL, ref, NULL) );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault)
+{
+ OSErr result;
+ FSVolumeRefNum vRefNum;
+ long dirID;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action((NULL != newDefault) && (NULL != oldDefault), BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of newDefault */
+ result = FSGetCatalogInfo(newDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure newDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), NewDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Get the current working directory. */
+ result = HGetVol(NULL, &vRefNum, &dirID);
+ require_noerr(result, HGetVol);
+
+ /* Return the oldDefault FSRef */
+ result = FSMakeFSRef(vRefNum, dirID, NULL, oldDefault);
+ require_noerr(result, FSMakeFSRef);
+
+ /* Set the new current working directory */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+FSMakeFSRef:
+HGetVol:
+NewDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault)
+{
+ OSErr result;
+ FSCatalogInfo catalogInfo;
+
+ /* check parameters */
+ require_action(NULL != oldDefault, BadParameter, result = paramErr);
+
+ /* Get nodeFlags, vRefNum and dirID (nodeID) of oldDefault */
+ result = FSGetCatalogInfo(oldDefault,
+ kFSCatInfoNodeFlags + kFSCatInfoVolume + kFSCatInfoNodeID,
+ &catalogInfo, NULL, NULL, NULL);
+ require_noerr(result, FSGetCatalogInfo);
+
+ /* Make sure oldDefault is a directory */
+ require_action(0 != (kFSNodeIsDirectoryMask & catalogInfo.nodeFlags), OldDefaultNotDirectory,
+ result = dirNFErr);
+
+ /* Set the current working directory to oldDefault */
+ result = HSetVol(NULL, catalogInfo.volume, catalogInfo.nodeID);
+ require_noerr(result, HSetVol);
+
+HSetVol:
+OldDefaultNotDirectory:
+FSGetCatalogInfo:
+BadParameter:
+
+ return ( result );
+}
+
+/*****************************************************************************/
--- /dev/null
+/*
+ File: MoreFilesX.h
+
+ Contains: A collection of useful high-level File Manager routines
+ which use the HFS Plus APIs wherever possible.
+
+ Version: MoreFilesX 1.0.1
+
+ Copyright: © 1992-2002 by Apple Computer, Inc., all rights reserved.
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
+ ("Apple") in consideration of your agreement to the following terms, and your
+ use, installation, modification or redistribution of this Apple software
+ constitutes acceptance of these terms. If you do not agree with these terms,
+ please do not use, install, modify or redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject
+ to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
+ copyrights in this original Apple software (the "Apple Software"), to use,
+ reproduce, modify and redistribute the Apple Software, with or without
+ modifications, in source and/or binary forms; provided that if you redistribute
+ the Apple Software in its entirety and without modifications, you must retain
+ this notice and the following text and disclaimers in all such redistributions of
+ the Apple Software. Neither the name, trademarks, service marks or logos of
+ Apple Computer, Inc. may be used to endorse or promote products derived from the
+ Apple Software without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or implied,
+ are granted by Apple herein, including but not limited to any patent rights that
+ may be infringed by your derivative works or by other works in which the Apple
+ Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+ COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+ OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+ (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ File Ownership:
+
+ DRI: Apple Macintosh Developer Technical Support
+
+ Other Contact: For bug reports, consult the following page on
+ the World Wide Web:
+ http://developer.apple.com/bugreporter/
+
+ Technology: DTS Sample Code
+
+ Writers:
+
+ (JL) Jim Luther
+
+ Change History (most recent first):
+
+ <3> 4/19/02 JL [2853905] Fixed #if test around header includes.
+ <2> 4/19/02 JL [2853901] Updated standard disclaimer.
+ <1> 1/25/02 JL MoreFilesX 1.0
+
+ Notes:
+ What do those arrows in the documentation for each routine mean?
+
+ --> The parameter is an input
+
+ <-- The parameter is an output. The pointer to the variable
+ where the output will be returned (must not be NULL).
+
+ <** The parameter is an optional output. If it is not a
+ NULL pointer, it points to the variable where the output
+ will be returned. If it is a NULL pointer, the output will
+ not be returned and will possibly let the routine and the
+ File Manager do less work. If you don't need an optional output,
+ don't ask for it.
+ **> The parameter is an optional input. If it is not a
+ NULL pointer, it points to the variable containing the
+ input data. If it is a NULL pointer, the input is not used
+ and will possibly let the routine and the File Manager
+ do less work.
+*/
+
+#ifndef __MOREFILESX__
+#define __MOREFILESX__
+
+#ifndef __CARBON__
+ #if defined(__MACH__)
+ #include <Carbon/Carbon.h>
+ #else
+ #include <Carbon.h>
+ #endif
+#endif
+
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_IMPORT
+#pragma import on
+#endif
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=mac68k
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(push, 2)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack(2)
+#endif
+
+/*****************************************************************************/
+
+#ifndef WIN32
+#pragma mark ----- FinderInfo and ExtendedFinderInfo -----
+#endif
+
+/*
+ * FSGetFinderInfo and FSSetFinderInfo use these unions for Finder information.
+ */
+
+union FinderInfo
+{
+ FileInfo file;
+ FolderInfo folder;
+};
+typedef union FinderInfo FinderInfo;
+
+union ExtendedFinderInfo
+{
+ ExtendedFileInfo file;
+ ExtendedFolderInfo folder;
+};
+typedef union ExtendedFinderInfo ExtendedFinderInfo;
+
+/*****************************************************************************/
+
+#pragma mark ----- GetVolParmsInfoBuffer Macros -----
+
+/*
+ * Macros to get information out of GetVolParmsInfoBuffer.
+ */
+
+/* version 1 field getters */
+#define GetVolParmsInfoVersion(volParms) \
+ ((volParms)->vMVersion)
+#define GetVolParmsInfoAttrib(volParms) \
+ ((volParms)->vMAttrib)
+#define GetVolParmsInfoLocalHand(volParms) \
+ ((volParms)->vMLocalHand)
+#define GetVolParmsInfoServerAdr(volParms) \
+ ((volParms)->vMServerAdr)
+
+/* version 2 field getters (assume zero result if version < 2) */
+#define GetVolParmsInfoVolumeGrade(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMVolumeGrade : 0)
+#define GetVolParmsInfoForeignPrivID(volParms) \
+ (((volParms)->vMVersion >= 2) ? (volParms)->vMForeignPrivID : 0)
+
+/* version 3 field getters (assume zero result if version < 3) */
+#define GetVolParmsInfoExtendedAttributes(volParms) \
+ (((volParms)->vMVersion >= 3) ? (volParms)->vMExtendedAttributes : 0)
+
+/* attribute bits supported by all versions of GetVolParmsInfoBuffer */
+#define VolIsNetworkVolume(volParms) \
+ ((volParms)->vMServerAdr != 0)
+#define VolHasLimitFCBs(volParms) \
+ (((volParms)->vMAttrib & (1L << bLimitFCBs)) != 0)
+#define VolHasLocalWList(volParms) \
+ (((volParms)->vMAttrib & (1L << bLocalWList)) != 0)
+#define VolHasNoMiniFndr(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoMiniFndr)) != 0)
+#define VolHasNoVNEdit(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoVNEdit)) != 0)
+#define VolHasNoLclSync(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoLclSync)) != 0)
+#define VolHasTrshOffLine(volParms) \
+ (((volParms)->vMAttrib & (1L << bTrshOffLine)) != 0)
+#define VolHasNoSwitchTo(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSwitchTo)) != 0)
+#define VolHasNoDeskItems(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoDeskItems)) != 0)
+#define VolHasNoBootBlks(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoBootBlks)) != 0)
+#define VolHasAccessCntl(volParms) \
+ (((volParms)->vMAttrib & (1L << bAccessCntl)) != 0)
+#define VolHasNoSysDir(volParms) \
+ (((volParms)->vMAttrib & (1L << bNoSysDir)) != 0)
+#define VolHasExtFSVol(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasExtFSVol)) != 0)
+#define VolHasOpenDeny(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasOpenDeny)) != 0)
+#define VolHasCopyFile(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCopyFile)) != 0)
+#define VolHasMoveRename(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasMoveRename)) != 0)
+#define VolHasDesktopMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasDesktopMgr)) != 0)
+#define VolHasShortName(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasShortName)) != 0)
+#define VolHasFolderLock(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFolderLock)) != 0)
+#define VolHasPersonalAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasPersonalAccessPrivileges)) != 0)
+#define VolHasUserGroupList(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasUserGroupList)) != 0)
+#define VolHasCatSearch(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasCatSearch)) != 0)
+#define VolHasFileIDs(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasFileIDs)) != 0)
+#define VolHasBTreeMgr(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBTreeMgr)) != 0)
+#define VolHasBlankAccessPrivileges(volParms) \
+ (((volParms)->vMAttrib & (1L << bHasBlankAccessPrivileges)) != 0)
+#define VolSupportsAsyncRequests(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsAsyncRequests)) != 0)
+#define VolSupportsTrashVolumeCache(volParms) \
+ (((volParms)->vMAttrib & (1L << bSupportsTrashVolumeCache)) != 0)
+
+/* attribute bits supported by version 3 and greater versions of GetVolParmsInfoBuffer */
+#define VolIsEjectable(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsEjectable)) != 0)
+#define VolSupportsHFSPlusAPIs(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsHFSPlusAPIs)) != 0)
+#define VolSupportsFSCatalogSearch(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSCatalogSearch)) != 0)
+#define VolSupportsFSExchangeObjects(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsFSExchangeObjects)) != 0)
+#define VolSupports2TBFiles(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupports2TBFiles)) != 0)
+#define VolSupportsLongNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsLongNames)) != 0)
+#define VolSupportsMultiScriptNames(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsMultiScriptNames)) != 0)
+#define VolSupportsNamedForks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsNamedForks)) != 0)
+#define VolSupportsSubtreeIterators(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSubtreeIterators)) != 0)
+#define VolL2PCanMapFileBlocks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bL2PCanMapFileBlocks)) != 0)
+#define VolParentModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bParentModDateChanges)) != 0)
+#define VolAncestorModDateChanges(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bAncestorModDateChanges)) != 0)
+#define VolSupportsSymbolicLinks(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bSupportsSymbolicLinks)) != 0)
+#define VolIsAutoMounted(volParms) \
+ ((GetVolParmsInfoExtendedAttributes(volParms) & (1L << bIsAutoMounted)) != 0)
+
+/*****************************************************************************/
+
+#pragma mark ----- userPrivileges Bit Masks and Macros -----
+
+/*
+ * Bit masks and macros to get common information out of userPrivileges byte
+ * returned by FSGetCatalogInfo.
+ *
+ * Note: The userPrivileges byte is the same as the ioACUser byte returned
+ * by PBGetCatInfo, and is the 1's complement of the user's privileges
+ * byte returned in ioACAccess by PBHGetDirAccess. That's where the
+ * ioACUser names came from.
+ *
+ * The userPrivileges are user's effective privileges based on the
+ * user ID and the groups that user belongs to, and the owner, group,
+ * and everyone privileges for the given directory.
+ */
+
+enum
+{
+ /* mask for just the access restriction bits */
+ kioACUserAccessMask = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask +
+ kioACUserNoMakeChangesMask),
+ /* common access privilege settings */
+ kioACUserFull = 0x00, /* no access restiction bits on */
+ kioACUserNone = kioACUserAccessMask, /* all access restiction bits on */
+ kioACUserDropBox = (kioACUserNoSeeFolderMask +
+ kioACUserNoSeeFilesMask), /* make changes, but not see files or folders */
+ kioACUserBulletinBoard = kioACUserNoMakeChangesMask /* see files and folders, but not make changes */
+};
+
+
+/* Macros for testing ioACUser bits. */
+
+#define UserIsOwner(userPrivileges) \
+ (((userPrivileges) & kioACUserNotOwnerMask) == 0)
+#define UserHasFullAccess(userPrivileges) \
+ (((userPrivileges) & (kioACUserAccessMask)) == kioACUserFull)
+#define UserHasDropBoxAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserDropBox)
+#define UserHasBulletinBoard(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserBulletinBoard)
+#define UserHasNoAccess(userPrivileges) \
+ (((userPrivileges) & kioACUserAccessMask) == kioACUserNone)
+
+/*****************************************************************************/
+
+#pragma mark ----- File Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFork
+
+OSErr
+FSCopyFork(
+ SInt16 srcRefNum,
+ SInt16 dstRefNum,
+ void *copyBufferPtr,
+ ByteCount copyBufferSize);
+
+/*
+ The FSCopyFork function copies all data from the source fork to the
+ destination fork of open file forks and makes sure the destination EOF
+ is equal to the source EOF.
+
+ srcRefNum --> The source file reference number.
+ dstRefNum --> The destination file reference number.
+ copyBufferPtr --> Pointer to buffer to use during copy. The
+ buffer should be at least 4K-bytes minimum.
+ The larger the buffer, the faster the copy
+ (up to a point).
+ copyBufferSize --> The size of the copy buffer.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Volume Access Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolParms
+
+OSErr
+FSGetVolParms(
+ FSVolumeRefNum volRefNum,
+ UInt32 bufferSize,
+ GetVolParmsInfoBuffer *volParmsInfo,
+ UInt32 *actualInfoSize);
+
+/*
+ The FSGetVolParms function returns information about the characteristics
+ of a volume. A result of paramErr usually just means the volume doesn't
+ support GetVolParms and the feature you were going to check
+ for isn't available.
+
+ volRefNum --> Volume specification.
+ bufferSize --> Size of buffer pointed to by volParmsInfo.
+ volParmsInfo <-- A GetVolParmsInfoBuffer record where the volume
+ attributes information is returned.
+ actualInfoSize <-- The number of bytes actually returned
+ in volParmsInfo.
+
+ __________
+
+ Also see: The GetVolParmsInfoBuffer Macros for checking attribute bits
+ in this file
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVRefNum
+
+OSErr
+FSGetVRefNum(
+ const FSRef *ref,
+ FSVolumeRefNum *vRefNum);
+
+/*
+ The FSGetVRefNum function determines the volume reference
+ number of a volume from a FSRef.
+
+ ref --> The FSRef.
+ vRefNum <-- The volume reference number.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVInfo
+
+OSErr
+FSGetVInfo(
+ FSVolumeRefNum volume,
+ HFSUniStr255 *volumeName, /* can be NULL */
+ UInt64 *freeBytes, /* can be NULL */
+ UInt64 *totalBytes); /* can be NULL */
+
+/*
+ The FSGetVInfo function returns the name, available space (in bytes),
+ and total space (in bytes) for the specified volume.
+
+ volume --> The volume reference number.
+ volumeName <** An optional pointer to a HFSUniStr255.
+ If not NULL, the volume name will be returned in
+ the HFSUniStr255.
+ freeBytes <** An optional pointer to a UInt64.
+ If not NULL, the number of free bytes on the
+ volume will be returned in the UInt64.
+ totalBytes <** An optional pointer to a UInt64.
+ If not NULL, the total number of bytes on the
+ volume will be returned in the UInt64.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolFileSystemID
+
+OSErr
+FSGetVolFileSystemID(
+ FSVolumeRefNum volume,
+ UInt16 *fileSystemID, /* can be NULL */
+ UInt16 *signature); /* can be NULL */
+
+/*
+ The FSGetVolFileSystemID function returns the file system ID and signature
+ of a mounted volume. The file system ID identifies the file system
+ that handles requests to a particular volume. The signature identifies the
+ volume type of the volume (for example, FSID 0 is Macintosh HFS Plus, HFS
+ or MFS, where a signature of 0x4244 identifies the volume as HFS).
+ Here's a partial list of file system ID numbers (only Apple's file systems
+ are listed):
+ FSID File System
+ ----- -----------------------------------------------------
+ $0000 Macintosh HFS Plus, HFS or MFS
+ $0100 ProDOS File System
+ $0101 PowerTalk Mail Enclosures
+ $4147 ISO 9660 File Access (through Foreign File Access)
+ $4242 High Sierra File Access (through Foreign File Access)
+ $464D QuickTake File System (through Foreign File Access)
+ $4953 Macintosh PC Exchange (MS-DOS)
+ $4A48 Audio CD Access (through Foreign File Access)
+ $4D4B Apple Photo Access (through Foreign File Access)
+ $6173 AppleShare (later versions of AppleShare only)
+
+ See the Technical Note "FL 35 - Determining Which File System
+ Is Active" and the "Guide to the File System Manager" for more
+ information.
+
+ volume --> The volume reference number.
+ fileSystemID <** An optional pointer to a UInt16.
+ If not NULL, the volume's file system ID will
+ be returned in the UInt16.
+ signature <** An optional pointer to a UInt16.
+ If not NULL, the volume's signature will
+ be returned in the UInt16.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetMountedVolumes
+
+OSErr
+FSGetMountedVolumes(
+ FSRef ***volumeRefsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numVolumes);
+
+/*
+ The FSGetMountedVolumes function returns the list of volumes currently
+ mounted in an array of FSRef records. The array of FSRef records is
+ returned in a Handle, volumeRefsHandle, which is allocated by
+ FSGetMountedVolumes. The caller is responsible for disposing of
+ volumeRefsHandle if the FSGetMountedVolumes returns noErr.
+
+ volumeRefsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numVolumes <-- The number of volumes returned in the array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- FSRef/FSpec/Path/Name Conversion Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefMakeFSSpec
+
+OSErr
+FSRefMakeFSSpec(
+ const FSRef *ref,
+ FSSpec *spec);
+
+/*
+ The FSRefMakeFSSpec function returns an FSSpec for the file or
+ directory specified by the ref parameter.
+
+ ref --> An FSRef specifying the file or directory.
+ spec <-- The FSSpec.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakeFSRef
+
+OSErr
+FSMakeFSRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ FSRef *ref);
+
+/*
+ The FSMakeFSRef function creates an FSRef from the traditional
+ volume reference number, directory ID and pathname inputs. It is
+ functionally equivalent to FSMakeFSSpec followed by FSpMakeFSRef.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ ref <-- The FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMakePath
+
+OSStatus
+FSMakePath(
+ SInt16 vRefNum,
+ SInt32 dirID,
+ ConstStr255Param name,
+ UInt8 *path,
+ UInt32 maxPathSize);
+
+/*
+ The FSMakePath function creates a pathname from the traditional volume reference
+ number, directory ID, and pathname inputs. It is functionally equivalent to
+ FSMakeFSSpec, FSpMakeFSRef, FSRefMakePath.
+
+ volRefNum --> Volume specification.
+ dirID --> Directory specification.
+ name --> The file or directory name, or NULL.
+ path <-- A pointer to a buffer which FSMakePath will
+ fill with a C string representing the pathname
+ to the file or directory specified. The format of
+ the pathname returned can be determined with the
+ Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname is a Mac OS File Manager full
+ pathname in a C string, and file or directory names
+ in the pathname may be mangled as returned by
+ the File Manager. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname is a UTF8 encoded POSIX absolute
+ pathname in a C string. In either case, the
+ pathname returned can be passed back to
+ FSPathMakeRef to create an FSRef to the file or
+ directory, or FSPathMakeFSSpec to craete an FSSpec
+ to the file or directory.
+ maxPathSize --> The size of the path buffer in bytes. If the path
+ buffer is too small for the pathname string,
+ FSMakePath returns pathTooLongErr or
+ buffersTooSmall.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSPathMakeFSSpec
+
+OSStatus
+FSPathMakeFSSpec(
+ const UInt8 *path,
+ FSSpec *spec,
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSPathMakeFSSpec function converts a pathname to an FSSpec.
+
+ path --> A pointer to a C String that is the pathname. The
+ format of the pathname you must supply can be
+ determined with the Gestalt selector gestaltFSAttr's
+ gestaltFSUsesPOSIXPathsForConversion bit.
+ If the gestaltFSUsesPOSIXPathsForConversion bit is
+ clear, the pathname must be a Mac OS File Manager
+ full pathname in a C string. If the
+ gestaltFSUsesPOSIXPathsForConversion bit is set,
+ the pathname must be a UTF8 encoded POSIX absolute
+ pathname in a C string.
+ spec <-- The FSSpec.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the specified path is a directory, or false will
+ be returned in the Boolean if the specified path is
+ a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark UnicodeNameGetHFSName
+
+OSErr
+UnicodeNameGetHFSName(
+ UniCharCount nameLength,
+ const UniChar *name,
+ TextEncoding textEncodingHint,
+ Boolean isVolumeName,
+ Str31 hfsName);
+
+/*
+ The UnicodeNameGetHFSName function converts a Unicode string
+ to a Pascal Str31 (or Str27) string using an algorithm similar to that used
+ by the File Manager. Note that if the name is too long or cannot be converted
+ using the given text encoding hint, you will get an error instead of the
+ mangled name that the File Manager would return.
+
+ nameLength --> Number of UniChar in name parameter.
+ name --> The Unicode string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ isVolumeName --> If true, the output name will be limited to
+ 27 characters (kHFSMaxVolumeNameChars). If false,
+ the output name will be limited to 31 characters
+ (kHFSMaxFileNameChars).
+ hfsName <-- The hfsName as a Pascal string.
+
+ __________
+
+ Also see: HFSNameGetUnicodeName
+*/
+
+/*****************************************************************************/
+
+#pragma mark HFSNameGetUnicodeName
+
+OSErr
+HFSNameGetUnicodeName(
+ ConstStr31Param hfsName,
+ TextEncoding textEncodingHint,
+ HFSUniStr255 *unicodeName);
+
+/*
+ The HFSNameGetUnicodeName function converts a Pascal Str31 string to an
+ Unicode HFSUniStr255 string using the same routines as the File Manager.
+
+ hfsName --> The Pascal string to convert.
+ textEncodingHint --> The text encoding hint used for the conversion.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ unicodeName <-- The Unicode string.
+
+ __________
+
+ Also see: UnicodeNameGetHFSName
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File/Directory Manipulation Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSRefValid
+
+Boolean FSRefValid(const FSRef *ref);
+
+/*
+ The FSRefValid function determines if an FSRef is valid. If the result is
+ true, then the FSRef refers to an existing file or directory.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetParentRef
+
+OSErr
+FSGetParentRef(
+ const FSRef *ref,
+ FSRef *parentRef);
+
+/*
+ The FSGetParentRef function gets the parent directory FSRef of the
+ specified object.
+
+ Note: FSRefs always point to real file system objects. So, there cannot
+ be a FSRef to the parent of volume root directories. If you call
+ FSGetParentRef with a ref to the root directory of a volume, the
+ function result will be noErr and the parentRef will be invalid (using it
+ for other file system requests will fail).
+
+ ref --> FSRef to a file or directory.
+ parentRef <-- The parent directory's FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFileDirName
+
+OSErr
+FSGetFileDirName(
+ const FSRef *ref,
+ HFSUniStr255 *outName);
+
+/*
+ The FSGetFileDirName function gets the name of the file or directory
+ specified.
+
+ ref --> FSRef to a file or directory.
+ outName <-- The file or directory name.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetNodeID
+
+OSErr
+FSGetNodeID(
+ const FSRef *ref,
+ long *nodeID, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The GetNodeIDFromFSRef function gets the node ID number of the
+ file or directory specified (note: the node ID is the directory ID
+ for directories).
+
+ ref --> FSRef to a file or directory.
+ nodeID <** An optional pointer to a long.
+ If not NULL, the node ID will be returned in
+ the long.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetUserPrivilegesPermissions
+
+OSErr
+FSGetUserPrivilegesPermissions(
+ const FSRef *ref,
+ UInt8 *userPrivileges, /* can be NULL */
+ UInt32 permissions[4]); /* can be NULL */
+
+/*
+ The FSGetUserPrivilegesPermissions function gets the userPrivileges and/or
+ permissions of the file or directory specified.
+
+ ref --> FSRef to a file or directory.
+ userPrivileges <** An optional pointer to a UInt8.
+ If not NULL, the userPrivileges will be returned
+ in the UInt8.
+ permissions <** An optional pointer to an UInt32[4] array.
+ If not NULL, the permissions will be returned
+ in the UInt32[4] array.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCheckLock
+
+OSErr
+FSCheckLock(
+ const FSRef *ref);
+
+/*
+ The FSCheckLock function determines if a file or directory is locked.
+ If FSCheckLock returns noErr, then the file or directory is not locked
+ and the volume it is on is not locked either. If FSCheckLock returns
+ fLckdErr, then the file or directory is locked. If FSCheckLock returns
+ wPrErr, then the volume is locked by hardware (i.e., locked tab on
+ removable media). If FSCheckLock returns vLckdErr, then the volume is
+ locked by software.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetForkSizes
+
+OSErr
+FSGetForkSizes(
+ const FSRef *ref,
+ UInt64 *dataLogicalSize, /* can be NULL */
+ UInt64 *rsrcLogicalSize); /* can be NULL */
+
+/*
+ The FSGetForkSizes returns the size of the data and/or resource fork for
+ the specified file.
+
+ ref --> FSRef to a file or directory.
+ dataLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the data fork's size will be
+ returned in the UInt64.
+ rsrcLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the resource fork's size will be
+ returned in the UInt64.
+
+ __________
+
+ Also see: FSGetTotalForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetTotalForkSizes
+
+OSErr
+FSGetTotalForkSizes(
+ const FSRef *ref,
+ UInt64 *totalLogicalSize, /* can be NULL */
+ UInt64 *totalPhysicalSize, /* can be NULL */
+ ItemCount *forkCount); /* can be NULL */
+
+/*
+ The FSGetTotalForkSizes returns the total logical size and/or the total
+ physical size of the specified file (i.e., it adds the sizes of all file
+ forks). It optionally returns the number of file forks.
+
+ ref --> FSRef to a file or directory.
+ totalLogicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork logical sizes
+ will be returned in the UInt64.
+ totalPhysicalSize <** An optional pointer to a UInt64.
+ If not NULL, the sum of all fork physical sizes
+ will be returned in the UInt64.
+ forkCount <** An optional pointer to a ItemCount.
+ If not NULL, the number of file forks
+ will be returned in the ItemCount.
+
+ __________
+
+ Also see: FSGetForkSizes
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSBumpDate
+
+OSErr
+FSBumpDate(
+ const FSRef *ref);
+
+/*
+ The FSBumpDate function changes the content modification date of a file
+ or directory to the current date/time. If the content modification date
+ is already equal to the current date/time, then add one second to the
+ content modification date.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetFinderInfo
+
+OSErr
+FSGetFinderInfo(
+ const FSRef *ref,
+ FinderInfo *info, /* can be NULL */
+ ExtendedFinderInfo *extendedInfo, /* can be NULL */
+ Boolean *isDirectory); /* can be NULL */
+
+/*
+ The FSGetFinderInfo function gets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info <** An optional pointer to a FinderInfo.
+ If not NULL, the FileInfo (if ref is a file) or
+ the FolderInfo (if ref is a folder) will be
+ returned in the FinderInfo.
+ extendedInfo <** An optional pointer to a ExtendedFinderInfo.
+ If not NULL, the ExtendedFileInfo (if ref is a file)
+ or the ExtendedFolderInfo (if ref is a folder) will
+ be returned in the ExtendedFinderInfo.
+ isDirectory <** An optional pointer to a Boolean.
+ If not NULL, true will be returned in the Boolean
+ if the object is a directory, or false will be
+ returned in the Boolean if object is a file.
+
+ __________
+
+ Also see: FSSetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetFinderInfo
+
+OSErr
+FSSetFinderInfo(
+ const FSRef *ref,
+ const FinderInfo *info, /* can be NULL */
+ const ExtendedFinderInfo *extendedInfo); /* can be NULL */
+
+/*
+ The FSSetFinderInfo function sets the finder information for a file or
+ directory.
+
+ ref --> FSRef to a file or directory.
+ info **> A pointer to a FinderInfo record with the new
+ FileInfo (if ref is a file) or new FolderInfo
+ (if ref is a folder), or NULL if the FinderInfo
+ is not to be changed.
+ extendedInfo **> A pointer to a FinderInfo record with the new
+ ExtendedFileInfo (if ref is a file) or new
+ ExtendedFolderInfo (if ref is a folder), or NULL
+ if the ExtendedFinderInfo is not to be changed.
+
+ __________
+
+ Also see: FSGetFinderInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeCreatorType
+
+OSErr
+FSChangeCreatorType(
+ const FSRef *ref,
+ OSType fileCreator,
+ OSType fileType);
+
+/*
+ The FSChangeCreatorType function changes the creator and/or file type of a file.
+
+ ref --> FSRef to a file.
+ creator --> The new creator type or 0x00000000 to leave
+ the creator type alone.
+ fileType --> The new file type or 0x00000000 to leave the
+ file type alone.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSChangeFinderFlags
+
+OSErr
+FSChangeFinderFlags(
+ const FSRef *ref,
+ Boolean setBits,
+ UInt16 flagBits);
+
+/*
+ The FSChangeFinderFlags function sets or clears flag bits in
+ the finderFlags field of a file's FileInfo record or a
+ directory's FolderInfo record.
+
+ ref --> FSRef to a file or directory.
+ setBits --> If true, then set the bits specified in flagBits.
+ If false, then clear the bits specified in flagBits.
+ flagBits --> The flagBits parameter specifies which Finder Flag
+ bits to set or clear. If a bit in flagBits is set,
+ then the same bit in fdFlags is either set or
+ cleared depending on the state of the setBits
+ parameter.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetInvisible
+
+OSErr
+FSSetInvisible(
+ const FSRef *ref);
+
+#pragma mark FSClearInvisible
+
+OSErr
+FSClearInvisible(
+ const FSRef *ref);
+
+/*
+ The FSSetInvisible and FSClearInvisible functions set or clear the
+ kIsInvisible bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetNameLocked
+
+OSErr
+FSSetNameLocked(
+ const FSRef *ref);
+
+#pragma mark FSClearNameLocked
+
+OSErr
+FSClearNameLocked(
+ const FSRef *ref);
+
+/*
+ The FSSetNameLocked and FSClearNameLocked functions set or clear the
+ kNameLocked bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetIsStationery
+
+OSErr
+FSSetIsStationery(
+ const FSRef *ref);
+
+#pragma mark FSClearIsStationery
+
+OSErr
+FSClearIsStationery(
+ const FSRef *ref);
+
+/*
+ The FSSetIsStationery and FSClearIsStationery functions set or clear the
+ kIsStationery bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetHasCustomIcon
+
+OSErr
+FSSetHasCustomIcon(
+ const FSRef *ref);
+
+#pragma mark FSClearHasCustomIcon
+
+OSErr
+FSClearHasCustomIcon(
+ const FSRef *ref);
+
+/*
+ The FSSetHasCustomIcon and FSClearHasCustomIcon functions set or clear the
+ kHasCustomIcon bit bit in the finderFlags field of the specified file or
+ directory's finder information.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSClearHasBeenInited
+
+OSErr
+FSClearHasBeenInited(
+ const FSRef *ref);
+
+/*
+ The FSClearHasBeenInited function clears the kHasBeenInited bit in the
+ finderFlags field of the specified file or directory's finder information.
+
+ Note: There is no FSSetHasBeenInited function because ONLY the Finder
+ should set the kHasBeenInited bit.
+
+ ref --> FSRef to a file or directory.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFileMgrAttributes
+
+OSErr
+FSCopyFileMgrAttributes(
+ const FSRef *sourceRef,
+ const FSRef *destinationRef,
+ Boolean copyLockBit);
+
+/*
+ The CopyFileMgrAttributes function copies all File Manager attributes
+ from the source file or directory to the destination file or directory.
+ If copyLockBit is true, then set the locked state of the destination
+ to match the source.
+
+ sourceRef --> FSRef to a file or directory.
+ destinationRef --> FSRef to a file or directory.
+ copyLockBit --> If true, set the locked state of the destination
+ to match the source.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRenameObjectUnicode
+
+OSErr
+FSMoveRenameObjectUnicode(
+ const FSRef *ref,
+ const FSRef *destDirectory,
+ UniCharCount nameLength,
+ const UniChar *name, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* if function fails along the way, newRef is final location of file */
+
+/*
+ The FSMoveRenameObjectUnicode function moves a file or directory and
+ optionally renames it. The source and destination locations must be on
+ the same volume.
+
+ Note: If the input ref parameter is invalid, this call will fail and
+ newRef, like ref, will be invalid.
+
+ ref --> FSRef to a file or directory.
+ destDirectory --> FSRef to the destination directory.
+ nameLength --> Number of UniChar in name parameter.
+ name --> An Unicode string with the new name for the
+ moved object, or NULL if no rename is wanted.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <-- The new FSRef of the object moved. Note that if
+ this function fails at any step along the way,
+ newRef is still then final location of the object.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainerContents
+
+OSErr
+FSDeleteContainerContents(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainerContents function deletes the contents of a container
+ directory. All files and subdirectories in the specified container are
+ deleted. If a locked file or directory is encountered, it is unlocked and
+ then deleted. If any unexpected errors are encountered,
+ FSDeleteContainerContents quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteContainer
+
+OSErr
+FSDeleteContainer(
+ const FSRef *container);
+
+/*
+ The FSDeleteContainer function deletes a container directory and its contents.
+ All files and subdirectories in the specified container are deleted.
+ If a locked file or directory is encountered, it is unlocked and then
+ deleted. After deleting the container's contents, the container is
+ deleted. If any unexpected errors are encountered, FSDeleteContainer
+ quits and returns to the caller.
+
+ container --> FSRef to a directory.
+
+ __________
+
+ Also see: FSDeleteContainerContents
+*/
+
+/*****************************************************************************/
+
+#pragma mark IterateContainerFilterProcPtr
+
+typedef CALLBACK_API( Boolean , IterateContainerFilterProcPtr ) (
+ Boolean containerChanged,
+ ItemCount currentLevel,
+ const FSCatalogInfo *catalogInfo,
+ const FSRef *ref,
+ const FSSpec *spec,
+ const HFSUniStr255 *name,
+ void *yourDataPtr);
+
+/*
+ This is the prototype for the IterateContainerFilterProc function which
+ is called once for each file and directory found by FSIterateContainer.
+ The IterateContainerFilterProc can use the read-only data it receives for
+ whatever it wants.
+
+ The result of the IterateContainerFilterProc function indicates if
+ iteration should be stopped. To stop iteration, return true; to continue
+ iteration, return false.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within the IterateContainerFilterProc.
+
+ containerChanged --> Set to true if the container's contents changed
+ during iteration.
+ currentLevel --> The current recursion level into the container.
+ 1 = the container, 2 = the container's immediate
+ subdirectories, etc.
+ catalogInfo --> The catalog information for the current object.
+ Only the fields requested by the whichInfo
+ parameter passed to FSIterateContainer are valid.
+ ref --> The FSRef to the current object.
+ spec --> The FSSpec to the current object if the wantFSSpec
+ parameter passed to FSIterateContainer is true.
+ name --> The name of the current object if the wantName
+ parameter passed to FSIterateContainer is true.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+ result <-- To stop iteration, return true; to continue
+ iteration, return false.
+
+ __________
+
+ Also see: FSIterateContainer
+*/
+
+/*****************************************************************************/
+
+#pragma mark CallIterateContainerFilterProc
+
+#define CallIterateContainerFilterProc(userRoutine, containerChanged, currentLevel, catalogInfo, ref, spec, name, yourDataPtr) \
+ (*(userRoutine))((containerChanged), (currentLevel), (catalogInfo), (ref), (spec), (name), (yourDataPtr))
+
+/*****************************************************************************/
+
+#pragma mark FSIterateContainer
+
+OSErr
+FSIterateContainer(
+ const FSRef *container,
+ ItemCount maxLevels,
+ FSCatalogInfoBitmap whichInfo,
+ Boolean wantFSSpec,
+ Boolean wantName,
+ IterateContainerFilterProcPtr iterateFilter,
+ void *yourDataPtr);
+
+/*
+ The FSIterateContainer function performs a recursive iteration (scan) of the
+ specified container directory and calls your IterateContainerFilterProc
+ function once for each file and directory found.
+
+ The maxLevels parameter lets you control how deep the recursion goes.
+ If maxLevels is 1, FSIterateContainer only scans the specified directory;
+ if maxLevels is 2, FSIterateContainer scans the specified directory and
+ one subdirectory below the specified directory; etc. Set maxLevels to
+ zero to scan all levels.
+
+ The yourDataPtr parameter can point to whatever data structure you might
+ want to access from within your IterateContainerFilterProc.
+
+ container --> The FSRef to the container directory to iterate.
+ maxLevels --> Maximum number of directory levels to scan or
+ zero to scan all directory levels.
+ whichInfo --> The fields of the FSCatalogInfo you wish to get.
+ wantFSSpec --> Set to true if you want the FSSpec to each
+ object passed to your IterateContainerFilterProc.
+ wantName --> Set to true if you want the name of each
+ object passed to your IterateContainerFilterProc.
+ iterateFilter --> A pointer to the IterateContainerFilterProc you
+ want called once for each file and directory found
+ by FSIterateContainer.
+ yourDataPtr --> An optional pointer to whatever data structure you
+ might want to access from within the
+ IterateFilterProc.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirectoryItems
+
+OSErr
+FSGetDirectoryItems(
+ const FSRef *container,
+ FSRef ***refsHandle, /* pointer to handle of FSRefs */
+ ItemCount *numRefs,
+ Boolean *containerChanged);
+
+/*
+ The FSGetDirectoryItems function returns the list of items in the specified
+ container. The array of FSRef records is returned in a Handle, refsHandle,
+ which is allocated by FSGetDirectoryItems. The caller is responsible for
+ disposing of refsHandle if the FSGetDirectoryItems returns noErr.
+
+ container --> FSRef to a directory.
+ refsHandle <-- Pointer to an FSRef Handle where the array of
+ FSRefs is to be returned.
+ numRefs <-- The number of FSRefs returned in the array.
+ containerChanged <-- Set to true if the container changes while the
+ list of items is being obtained.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSExchangeObjectsCompat
+
+OSErr
+FSExchangeObjectsCompat(
+ const FSRef *sourceRef,
+ const FSRef *destRef,
+ FSRef *newSourceRef,
+ FSRef *newDestRef);
+
+/*
+ The FSExchangeObjectsCompat function exchanges the data between two files.
+
+ The FSExchangeObjectsCompat function is an enhanced version of
+ FSExchangeObjects function. The two enhancements FSExchangeObjectsCompat
+ provides are:
+
+ 1, FSExchangeObjectsCompat will work on volumes which do not support
+ FSExchangeObjects. FSExchangeObjectsCompat does this by emulating
+ FSExchangeObjects through a series of File Manager operations. If
+ there is a failure at any step along the way, FSExchangeObjectsCompat
+ attempts to undo any steps already taken to leave the files in their
+ original state in their original locations.
+
+ 2. FSExchangeObjectsCompat returns new FSRefs to the source and
+ destination files. Note that if this function fails at any step along
+ the way, newSourceRef and newDestRef still give you access to the final
+ locations of the files being exchanged -- even if they are renamed or
+ not in their original locations.
+
+ sourceRef --> FSRef to the source file.
+ destRef --> FSRef to the destination file.
+ newSourceRef <-- The new FSRef to the source file.
+ newDestRef <-- The new FSRef to the destination file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Shared Environment Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSLockRange
+
+OSErr
+FSLockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The LockRange function locks (denies access to) a portion of a file
+ that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to lock.
+
+ __________
+
+ Also see: UnlockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSUnlockRange
+
+OSErr
+FSUnlockRange(
+ SInt16 refNum,
+ SInt32 rangeLength,
+ SInt32 rangeStart);
+
+/*
+ The UnlockRange function unlocks (allows access to) a previously locked
+ portion of a file that was opened with shared read/write permission.
+
+ refNum --> The file reference number of an open file.
+ rangeLength --> The number of bytes in the range.
+ rangeStart --> The starting byte in the range to unlock.
+
+ __________
+
+ Also see: LockRange
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetDirAccess
+
+OSErr
+FSGetDirAccess(
+ const FSRef *ref,
+ SInt32 *ownerID, /* can be NULL */
+ SInt32 *groupID, /* can be NULL */
+ SInt32 *accessRights); /* can be NULL */
+
+/*
+ The FSGetDirAccess function retrieves the directory access control
+ information for a directory on a shared volume.
+
+ ref --> An FSRef specifying the directory.
+ ownerID <** An optional pointer to a SInt32.
+ If not NULL, the directory's owner ID
+ will be returned in the SInt32.
+ groupID <** An optional pointer to a SInt32.
+ If not NULL, the directory's group ID, or 0
+ if no group affiliation, will be returned in
+ the SInt32.
+ accessRights <** An optional pointer to a SInt32.
+ If not NULL, the directory's access rights
+ will be returned in the SInt32.
+
+ __________
+
+ Also see: FSSetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDirAccess
+
+OSErr
+FSSetDirAccess(
+ const FSRef *ref,
+ SInt32 ownerID,
+ SInt32 groupID,
+ SInt32 accessRights);
+
+/*
+ The FSpSetDirAccess function changes the directory access control
+ information for a directory on a shared volume. You must be the owner of
+ a directory to change its access control information.
+
+ ref --> An FSRef specifying the directory.
+ ownerID --> The directory's owner ID.
+ groupID --> The directory's group ID or 0 if no group affiliation.
+ accessRights --> The directory's access rights.
+
+ __________
+
+ Also see: FSGetDirAccess, FSMapID, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfoSize
+
+OSErr
+FSGetVolMountInfoSize(
+ FSVolumeRefNum volRefNum,
+ SInt16 *size);
+
+/*
+ The FSGetVolMountInfoSize function determines the how much space the
+ program needs to allocate for a volume mounting information record.
+
+ volRefNum --> Volume specification.
+ size <-- The space needed (in bytes) of the volume
+ mounting information record.
+
+ __________
+
+ Also see: FSGetVolMountInfo, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSGetVolMountInfo
+
+OSErr
+FSGetVolMountInfo(
+ FSVolumeRefNum volRefNum,
+ void *volMountInfo);
+
+/*
+ The FSGetVolMountInfo function retrieves a volume mounting information
+ record containing all the information needed to mount the volume,
+ except for passwords.
+
+ volRefNum --> Volume specification.
+ volMountInfo <-- The volume mounting information.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, VolumeMount
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSVolumeMount
+
+OSErr
+FSVolumeMount(
+ const void *volMountInfo,
+ FSVolumeRefNum *volRefNum);
+
+/*
+ The VolumeMount function mounts a volume using a volume mounting
+ information record.
+
+ volMountInfo --> A volume mounting information record.
+ volRefNum <-- The volume reference number.
+
+ __________
+
+ Also see: FSGetVolMountInfoSize, FSGetVolMountInfo
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapID
+
+OSErr
+FSMapID(
+ FSVolumeRefNum volRefNum,
+ SInt32 ugID,
+ SInt16 objType,
+ Str31 name);
+
+/*
+ The FSMapID function determines the name of a user or group if you know
+ the user or group ID.
+
+ volRefNum --> Volume specification.
+ objType --> The mapping function code:
+ kOwnerID2Name to map a user ID to a user name
+ kGroupID2Name to map a group ID to a group name
+ name <** An optional pointer to a buffer (minimum Str31).
+ If not NULL, the user or group name
+ will be returned in the buffer.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapName
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMapName
+
+OSErr
+FSMapName(
+ FSVolumeRefNum volRefNum,
+ ConstStr255Param name,
+ SInt16 objType,
+ SInt32 *ugID);
+
+/*
+ The FSMapName function determines the user or group ID if you know the
+ user or group name.
+
+ volRefNum --> Volume specification.
+ name --> The user or group name.
+ objType --> The mapping function code:
+ kOwnerName2ID to map a user name to a user ID
+ kGroupName2ID to map a user name to a group ID
+ ugID <-- The user or group ID.
+
+ __________
+
+ Also see: FSGetDirAccess, FSSetDirAccess, FSMapID
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCopyFile
+
+OSErr
+FSCopyFile(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *copyName, /* can be NULL (no rename during copy) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSCopyFile function duplicates a file and optionally renames it.
+ The source and destination volumes must be on the same file server.
+ This function instructs the server to copy the file.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in copyName parameter (ignored
+ if copyName is NULL).
+ copyName --> Points to the new file name if the file is to be
+ renamed, or NULL if the file isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the duplicated file
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSMoveRename
+
+OSErr
+FSMoveRename(
+ const FSRef *srcFileRef,
+ const FSRef *dstDirectoryRef,
+ UniCharCount nameLength,
+ const UniChar *moveName, /* can be NULL (no rename during move) */
+ TextEncoding textEncodingHint,
+ FSRef *newRef); /* can be NULL */
+
+/*
+ The FSMoveRename function moves a file or directory (object), and
+ optionally renames it. The source and destination locations must be on
+ the same shared volume.
+
+ srcFileRef --> An FSRef specifying the source file.
+ dstDirectoryRef --> An FSRef specifying the destination directory.
+ nameLength --> Number of UniChar in moveName parameter (ignored
+ if copyName is NULL)
+ moveName --> Points to the new object name if the object is to be
+ renamed, or NULL if the object isn't to be renamed.
+ textEncodingHint --> The text encoding hint used for the rename.
+ You can pass kTextEncodingUnknown to use the
+ "default" textEncodingHint.
+ newRef <** An optional pointer to a FSRef.
+ If not NULL, the FSRef of the moved object
+ will be returned in the FSRef.
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- File ID Routines -----
+
+/*****************************************************************************/
+
+#pragma mark FSResolveFileIDRef
+
+OSErr
+FSResolveFileIDRef(
+ FSVolumeRefNum volRefNum,
+ SInt32 fileID,
+ FSRef *ref);
+
+/*
+ The FSResolveFileIDRef function returns an FSRef for the file with the
+ specified file ID reference.
+
+ volRefNum --> Volume specification.
+ fileID --> The file ID reference.
+ ref <-- The FSRef for the file ID reference.
+
+ __________
+
+ Also see: FSCreateFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSCreateFileIDRef
+
+OSErr
+FSCreateFileIDRef(
+ const FSRef *ref,
+ SInt32 *fileID);
+
+/*
+ The FSCreateFileIDRef function creates a file ID reference for the
+ specified file, or if a file ID reference already exists, supplies
+ the file ID reference and returns the result code fidExists or afpIDExists.
+
+ ref --> The FSRef for the file.
+ fileID <-- The file ID reference (if result is noErr,
+ fidExists, or afpIDExists).
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSDeleteFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSDeleteFileIDRef
+
+/*
+ Why is there no FSDeleteFileIDRef routine? There are two reasons:
+
+ 1. Since Mac OS 8.1, PBDeleteFileIDRef hasn't deleted file ID references.
+ On HFS volumes, deleting a file ID reference breaks aliases (which
+ use file ID references to track files as they are moved around on a
+ volume) and file ID references are automatically deleted when the file
+ they refer to is deleted. On HFS Plus volumes, file ID references are
+ always created when a file is created, deleted when the file is deleted,
+ and cannot be deleted at any other time.
+
+ 2. PBDeleteFileIDRef causes a memory access fault under Mac OS X 10.0
+ through 10.1.x. While this will be fixed in a future release, the
+ implementation, like the Mac OS 8/9 implementation, does not delete
+ file ID references.
+
+ __________
+
+ Also see: GetFSRefFromFileIDRef, FSCreateFileIDRef
+*/
+
+/*****************************************************************************/
+
+#pragma mark ----- Utility Routines -----
+
+/*****************************************************************************/
+
+#pragma mark GetTempBuffer
+
+Ptr
+GetTempBuffer(
+ ByteCount buffReqSize,
+ ByteCount *buffActSize);
+
+/*
+ The GetTempBuffer function allocates a temporary buffer for file system
+ operations which is at least 4K bytes and a multiple of 4K bytes.
+
+ buffReqSize --> Size you'd like the buffer to be.
+ buffActSize <-- The size of the buffer allocated.
+ function result <-- Pointer to memory allocated, or NULL if no memory
+ was available. The caller is responsible for
+ disposing of this buffer with DisposePtr.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FileRefNumGetFSRef
+
+OSErr
+FileRefNumGetFSRef(
+ short refNum,
+ FSRef *ref);
+
+/*
+ The FileRefNumGetFSRef function gets the FSRef of an open file.
+
+ refNum --> The file reference number of an open file.
+ ref <-- The FSRef to the open file.
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSSetDefault
+
+OSErr
+FSSetDefault(
+ const FSRef *newDefault,
+ FSRef *oldDefault);
+
+/*
+ The FSSetDefault function sets the current working directory to the
+ directory specified by newDefault. The previous current working directory
+ is returned in oldDefault and must be used to restore the current working
+ directory to its previous state with the FSRestoreDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ newDefault --> An FSRef that specifies the new current working
+ directory.
+ oldDefault <-- The previous current working directory's FSRef.
+
+ __________
+
+ Also see: FSRestoreDefault
+*/
+
+/*****************************************************************************/
+
+#pragma mark FSRestoreDefault
+
+OSErr
+FSRestoreDefault(
+ const FSRef *oldDefault);
+
+/*
+ The FSRestoreDefault function restores the current working directory
+ to the directory specified by oldDefault. The oldDefault parameter was
+ previously obtained from the FSSetDefault function.
+ These two functions are designed to be used as a wrapper around
+ Standard I/O routines where the location of the file is implied to be the
+ current working directory. This is how you should use these functions:
+
+ result = FSSetDefault(&newDefault, &oldDefault);
+ if ( noErr == result )
+ {
+ // call the Stdio functions like remove, rename,
+ // fopen, freopen, etc here!
+
+ result = FSRestoreDefault(&oldDefault);
+ }
+
+ oldDefault --> The FSRef of the location to restore.
+
+ __________
+
+ Also see: FSSetDefault
+*/
+
+/*****************************************************************************/
+
+#if PRAGMA_STRUCT_ALIGN
+ #pragma options align=reset
+#elif PRAGMA_STRUCT_PACKPUSH
+ #pragma pack(pop)
+#elif PRAGMA_STRUCT_PACK
+ #pragma pack()
+#endif
+
+#ifdef PRAGMA_IMPORT_OFF
+#pragma import off
+#elif PRAGMA_IMPORT
+#pragma import reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MOREFILESX__ */
+
--- /dev/null
+#include "Objects.h"
+extern XYZ viewer;
+extern float viewdistance;
+extern float lightambient[3],lightbrightness[3];
+extern float fadestart;
+extern int environment;
+extern float texscale;
+extern Light light;
+extern float multiplier;
+extern float gravity;
+extern FRUSTUM frustum;
+extern Terrain terrain;
+extern float terraindetail;
+extern bool foliage;
+extern int detail;
+extern float blurness;
+extern float windvar;
+extern float playerdist;
+extern bool skyboxtexture;
+extern Sprites sprites;
+
+//Functions
+
+bool Objects::checkcollide(XYZ startpoint,XYZ endpoint,int which){
+ static XYZ colpoint,colviewer,coltarget;
+ static int i;
+
+ startpoint.y+=.1;
+ endpoint.y+=.1;
+ startpoint.y-=.1;
+ endpoint.y-=.1;
+
+ for(i=0;i<numobjects;i++){
+ if(type[i]!=treeleavestype&&type[i]!=treetrunktype&&type[i]!=bushtype&&type[i]!=firetype&&i!=which){
+ colviewer=startpoint;
+ coltarget=endpoint;
+ if(model[i].LineCheck(&colviewer,&coltarget,&colpoint,&position[i],&rotation[i])!=-1)return 1;
+ }
+ }
+
+ return 0;
+}
+
+void Objects::SphereCheckPossible(XYZ *p1,float radius)
+{
+ static int i,j;
+ static int whichpatchx;
+ static int whichpatchz;
+
+ whichpatchx=p1->x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=p1->z/(terrain.size/subdivision*terrain.scale*terraindetail);
+
+ if(whichpatchx>=0&&whichpatchz>=0&&whichpatchx<subdivision&&whichpatchz<subdivision)
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz]>0&&terrain.patchobjectnum[whichpatchx][whichpatchz]<500)
+ for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
+ i=terrain.patchobjects[whichpatchx][whichpatchz][j];
+ possible[i]=0;
+ if(model[i].SphereCheckPossible(p1, radius, &position[i], &rotation[i])!=-1){
+ possible[i]=1;
+ }
+ }
+}
+
+void Objects::Draw()
+{
+ static float distance;
+ static int i,j;
+ static XYZ moved,terrainlight;
+ bool hidden;
+
+ for(i=0;i<numobjects;i++){
+ if(type[i]!=firetype){
+ moved=DoRotation(model[i].boundingspherecenter,0,rotation[i],0);
+ if(type[i]==tunneltype||frustum.SphereInFrustum(position[i].x+moved.x,position[i].y+moved.y,position[i].z+moved.z,model[i].boundingsphereradius)){
+ distance=findDistancefast(&viewer,&position[i]);
+ distance*=1.2;
+ hidden=!(findDistancefastflat(&viewer,&position[i])>playerdist+3||(type[i]!=bushtype&&type[i]!=treeleavestype));
+ if(!hidden){
+
+ if(detail==2&&distance>viewdistance*viewdistance/4&&environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness );
+ else glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
+ distance=(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance;
+ if(distance>1)distance=1;
+ if(distance>0){
+
+ /*if(checkcollide(viewer,DoRotation(model[i].vertex[model[i].vertexNum],0,rotation[i],0)*scale[i]+position[i],i)){
+ occluded[i]+=1;
+ }
+ else occluded[i]=0;*/
+ if(occluded[i]<6){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(!model[i].color)glEnable(GL_LIGHTING);
+ else glDisable(GL_LIGHTING);
+ glDepthMask(1);
+ glTranslatef(position[i].x,position[i].y,position[i].z);
+ if(type[i]==bushtype){
+ messedwith[i]-=multiplier;
+ if(rotxvel[i]||rotx[i]){
+ if(rotx[i]>0)rotxvel[i]-=multiplier*8*abs(rotx[i]);
+ if(rotx[i]<0)rotxvel[i]+=multiplier*8*abs(rotx[i]);
+ if(rotx[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotx[i]<0)rotxvel[i]+=multiplier*4;
+ if(rotxvel[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotxvel[i]<0)rotxvel[i]+=multiplier*4;
+ if(abs(rotx[i])<multiplier*4)rotx[i]=0;
+ if(abs(rotxvel[i])<multiplier*4)rotxvel[i]=0;
+
+ rotx[i]+=rotxvel[i]*multiplier*4;
+ }
+ if(rotyvel[i]||roty[i]){
+ if(roty[i]>0)rotyvel[i]-=multiplier*8*abs(roty[i]);
+ if(roty[i]<0)rotyvel[i]+=multiplier*8*abs(roty[i]);
+ if(roty[i]>0)rotyvel[i]-=multiplier*4;
+ if(roty[i]<0)rotyvel[i]+=multiplier*4;
+ if(rotyvel[i]>0)rotyvel[i]-=multiplier*4;
+ if(rotyvel[i]<0)rotyvel[i]+=multiplier*4;
+ if(abs(roty[i])<multiplier*4)roty[i]=0;
+ if(abs(rotyvel[i])<multiplier*4)rotyvel[i]=0;
+
+ roty[i]+=rotyvel[i]*multiplier*4;
+ }
+ if(roty[i]){
+ glRotatef(roty[i],1,0,0);
+ }
+ if(rotx[i]){
+ glRotatef(-rotx[i],0,0,1);
+ }
+ if(rotx[i]>10)rotx[i]=10;
+ if(rotx[i]<-10)rotx[i]=-10;
+ if(roty[i]>10)roty[i]=10;
+ if(roty[i]<-10)roty[i]=-10;
+ }
+ if(type[i]==treetrunktype||type[i]==treeleavestype){
+ if(type[i]==treetrunktype||environment==2){
+ messedwith[i]-=multiplier;
+ if(rotxvel[i]||rotx[i]){
+ if(rotx[i]>0)rotxvel[i]-=multiplier*8*abs(rotx[i]);
+ if(rotx[i]<0)rotxvel[i]+=multiplier*8*abs(rotx[i]);
+ if(rotx[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotx[i]<0)rotxvel[i]+=multiplier*4;
+ if(rotxvel[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotxvel[i]<0)rotxvel[i]+=multiplier*4;
+ if(abs(rotx[i])<multiplier*4)rotx[i]=0;
+ if(abs(rotxvel[i])<multiplier*4)rotxvel[i]=0;
+
+ rotx[i]+=rotxvel[i]*multiplier*4;
+ }
+ if(rotyvel[i]||roty[i]){
+ if(roty[i]>0)rotyvel[i]-=multiplier*8*abs(roty[i]);
+ if(roty[i]<0)rotyvel[i]+=multiplier*8*abs(roty[i]);
+ if(roty[i]>0)rotyvel[i]-=multiplier*4;
+ if(roty[i]<0)rotyvel[i]+=multiplier*4;
+ if(rotyvel[i]>0)rotyvel[i]-=multiplier*4;
+ if(rotyvel[i]<0)rotyvel[i]+=multiplier*4;
+ if(abs(roty[i])<multiplier*4)roty[i]=0;
+ if(abs(rotyvel[i])<multiplier*4)rotyvel[i]=0;
+
+ roty[i]+=rotyvel[i]*multiplier*4;
+ }
+ if(roty[i]){
+ glRotatef(roty[i]/6,1,0,0);
+ }
+ if(rotx[i]){
+ glRotatef(-rotx[i]/6,0,0,1);
+ }
+ if(rotx[i]>10)rotx[i]=10;
+ if(rotx[i]<-10)rotx[i]=-10;
+ if(roty[i]>10)roty[i]=10;
+ if(roty[i]<-10)roty[i]=-10;
+ }
+ else
+ {
+ messedwith[i]-=multiplier;
+ if(rotxvel[i]||rotx[i]){
+ if(rotx[i]>0)rotxvel[i]-=multiplier*8*abs(rotx[i]);
+ if(rotx[i]<0)rotxvel[i]+=multiplier*8*abs(rotx[i]);
+ if(rotx[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotx[i]<0)rotxvel[i]+=multiplier*4;
+ if(rotxvel[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotxvel[i]<0)rotxvel[i]+=multiplier*4;
+ if(abs(rotx[i])<multiplier*4)rotx[i]=0;
+ if(abs(rotxvel[i])<multiplier*4)rotxvel[i]=0;
+
+ rotx[i]+=rotxvel[i]*multiplier*4;
+ }
+ if(rotyvel[i]||roty[i]){
+ if(roty[i]>0)rotyvel[i]-=multiplier*8*abs(roty[i]);
+ if(roty[i]<0)rotyvel[i]+=multiplier*8*abs(roty[i]);
+ if(roty[i]>0)rotyvel[i]-=multiplier*4;
+ if(roty[i]<0)rotyvel[i]+=multiplier*4;
+ if(rotyvel[i]>0)rotyvel[i]-=multiplier*4;
+ if(rotyvel[i]<0)rotyvel[i]+=multiplier*4;
+ if(abs(roty[i])<multiplier*4)roty[i]=0;
+ if(abs(rotyvel[i])<multiplier*4)rotyvel[i]=0;
+
+ roty[i]+=rotyvel[i]*multiplier*4;
+ }
+ if(roty[i]){
+ glRotatef(roty[i]/4,1,0,0);
+ }
+ if(rotx[i]){
+ glRotatef(-rotx[i]/4,0,0,1);
+ }
+ if(rotx[i]>10)rotx[i]=10;
+ if(rotx[i]<-10)rotx[i]=-10;
+ if(roty[i]>10)roty[i]=10;
+ if(roty[i]<-10)roty[i]=-10;
+ }
+
+ }
+ if(/*detail==2&&*/environment==snowyenvironment){
+ if(type[i]==treeleavestype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*1.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==treetrunktype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==bushtype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*4*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ }
+ if(/*detail==2&&*/environment==grassyenvironment){
+ if(type[i]==treeleavestype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*1.5*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==treetrunktype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*.5*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==bushtype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*4*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ }
+ if(/*detail==2&&*/environment==desertenvironment){
+ if(type[i]==bushtype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*4*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ }
+ glRotatef(rotation[i],0,1,0);
+ if(distance>1)distance=1;
+ glColor4f((1-shadowed[i])/2+.5,(1-shadowed[i])/2+.5,(1-shadowed[i])/2+.5,distance);
+ if(distance>=1){
+ glDisable(GL_BLEND);
+ glAlphaFunc(GL_GREATER, 0.5);
+ }
+ if(distance<1){
+ glEnable(GL_BLEND);
+ glAlphaFunc(GL_GREATER, 0.1);
+ }
+ if(type[i]!=treetrunktype&&type[i]!=treeleavestype&&type[i]!=bushtype&&type[i]!=rocktype){
+ glEnable(GL_CULL_FACE);
+ glAlphaFunc(GL_GREATER, 0.0001);
+ model[i].drawdifftex(boxtextureptr);
+ model[i].drawdecals(terrain.shadowtexture,terrain.bloodtexture,terrain.bloodtexture2,terrain.breaktexture);
+ }
+ if(type[i]==rocktype){
+ glEnable(GL_CULL_FACE);
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glColor4f((1-shadowed[i])/2+light.ambient[0],(1-shadowed[i])/2+light.ambient[1],(1-shadowed[i])/2+light.ambient[2],distance);
+ model[i].drawdifftex(rocktextureptr);
+ model[i].drawdecals(terrain.shadowtexture,terrain.bloodtexture,terrain.bloodtexture2,terrain.breaktexture);
+ }
+ if(type[i]==treeleavestype){
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ if(!hidden){
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ if(distance<1)glAlphaFunc(GL_GREATER, 0.2);
+ }
+ if(hidden){
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance/3);
+ glAlphaFunc(GL_GREATER, 0);
+ }
+ model[i].drawdifftex(treetextureptr);
+ }
+ if(type[i]==bushtype){
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ if(!hidden){
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ if(distance<1)glAlphaFunc(GL_GREATER, 0.2);
+ }
+ if(hidden){
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance/3);
+ glAlphaFunc(GL_GREATER, 0);
+ }
+ model[i].drawdifftex(bushtextureptr);
+ }
+ if(type[i]==treetrunktype){
+ glEnable(GL_CULL_FACE);
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,distance);
+ model[i].drawdifftex(treetextureptr);
+ }
+ glPopMatrix();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
+ for(i=0;i<numobjects;i++){
+ if(type[i]==treeleavestype||type[i]==bushtype){
+ moved=DoRotation(model[i].boundingspherecenter,0,rotation[i],0);
+ if(frustum.SphereInFrustum(position[i].x+moved.x,position[i].y+moved.y,position[i].z+moved.z,model[i].boundingsphereradius)){
+ hidden=findDistancefastflat(&viewer,&position[i])<=playerdist+3;
+ if(hidden){
+ distance=1;
+ if(distance>0){
+ if(1==1||occluded[i]<6){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glEnable(GL_LIGHTING);
+ glDepthMask(1);
+ glTranslatef(position[i].x,position[i].y,position[i].z);
+ if(type[i]==bushtype){
+ messedwith[i]-=multiplier;
+ if(rotxvel[i]||rotx[i]){
+ if(rotx[i]>0)rotxvel[i]-=multiplier*8*abs(rotx[i]);
+ if(rotx[i]<0)rotxvel[i]+=multiplier*8*abs(rotx[i]);
+ if(rotx[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotx[i]<0)rotxvel[i]+=multiplier*4;
+ if(rotxvel[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotxvel[i]<0)rotxvel[i]+=multiplier*4;
+ if(abs(rotx[i])<multiplier*4)rotx[i]=0;
+ if(abs(rotxvel[i])<multiplier*4)rotxvel[i]=0;
+
+ rotx[i]+=rotxvel[i]*multiplier*4;
+ }
+ if(rotyvel[i]||roty[i]){
+ if(roty[i]>0)rotyvel[i]-=multiplier*8*abs(roty[i]);
+ if(roty[i]<0)rotyvel[i]+=multiplier*8*abs(roty[i]);
+ if(roty[i]>0)rotyvel[i]-=multiplier*4;
+ if(roty[i]<0)rotyvel[i]+=multiplier*4;
+ if(rotyvel[i]>0)rotyvel[i]-=multiplier*4;
+ if(rotyvel[i]<0)rotyvel[i]+=multiplier*4;
+ if(abs(roty[i])<multiplier*4)roty[i]=0;
+ if(abs(rotyvel[i])<multiplier*4)rotyvel[i]=0;
+
+ roty[i]+=rotyvel[i]*multiplier*4;
+ }
+ if(roty[i]){
+ glRotatef(roty[i],1,0,0);
+ }
+ if(rotx[i]){
+ glRotatef(-rotx[i],0,0,1);
+ }
+ if(rotx[i]>10)rotx[i]=10;
+ if(rotx[i]<-10)rotx[i]=-10;
+ if(roty[i]>10)roty[i]=10;
+ if(roty[i]<-10)roty[i]=-10;
+ }
+ if(type[i]==treetrunktype||type[i]==treeleavestype){
+ messedwith[i]-=multiplier;
+ if(rotxvel[i]||rotx[i]){
+ if(rotx[i]>0)rotxvel[i]-=multiplier*8*abs(rotx[i]);
+ if(rotx[i]<0)rotxvel[i]+=multiplier*8*abs(rotx[i]);
+ if(rotx[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotx[i]<0)rotxvel[i]+=multiplier*4;
+ if(rotxvel[i]>0)rotxvel[i]-=multiplier*4;
+ if(rotxvel[i]<0)rotxvel[i]+=multiplier*4;
+ if(abs(rotx[i])<multiplier*4)rotx[i]=0;
+ if(abs(rotxvel[i])<multiplier*4)rotxvel[i]=0;
+
+ rotx[i]+=rotxvel[i]*multiplier*4;
+ }
+ if(rotyvel[i]||roty[i]){
+ if(roty[i]>0)rotyvel[i]-=multiplier*8*abs(roty[i]);
+ if(roty[i]<0)rotyvel[i]+=multiplier*8*abs(roty[i]);
+ if(roty[i]>0)rotyvel[i]-=multiplier*4;
+ if(roty[i]<0)rotyvel[i]+=multiplier*4;
+ if(rotyvel[i]>0)rotyvel[i]-=multiplier*4;
+ if(rotyvel[i]<0)rotyvel[i]+=multiplier*4;
+ if(abs(roty[i])<multiplier*4)roty[i]=0;
+ if(abs(rotyvel[i])<multiplier*4)rotyvel[i]=0;
+
+ roty[i]+=rotyvel[i]*multiplier*4;
+ }
+ if(roty[i]){
+ glRotatef(roty[i]/2,1,0,0);
+ }
+ if(rotx[i]){
+ glRotatef(-rotx[i]/2,0,0,1);
+ }
+ if(rotx[i]>10)rotx[i]=10;
+ if(rotx[i]<-10)rotx[i]=-10;
+ if(roty[i]>10)roty[i]=10;
+ if(roty[i]<-10)roty[i]=-10;
+ }
+ if(environment==snowyenvironment){
+ if(type[i]==treeleavestype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*1.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==treetrunktype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==bushtype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*4*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ }
+ if(environment==grassyenvironment){
+ if(type[i]==treeleavestype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*1.5*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==treetrunktype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*.5*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ if(type[i]==bushtype){
+ glRotatef((sin(windvar+position[i].x*.3)+.5)*4*.5*(sin(windvar*2+position[i].x*.3)+1)/2,1,0,0);
+ }
+ }
+ glRotatef(rotation[i],0,1,0);
+ glColor4f(1,1,1,distance);
+ if(type[i]==treeleavestype){
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,.3);
+ glAlphaFunc(GL_GREATER, 0);
+ glDisable(GL_ALPHA_TEST);
+ model[i].drawdifftex(treetextureptr);
+ }
+ if(type[i]==bushtype){
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,.3);
+ glAlphaFunc(GL_GREATER, 0);
+ glDisable(GL_ALPHA_TEST);
+ model[i].drawdifftex(bushtextureptr);
+ }
+ glPopMatrix();
+ }
+ }
+ }
+ }
+ }
+ }
+ if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
+ glEnable(GL_ALPHA_TEST);
+ SetUpLight(&light,0);
+}
+
+void Objects::DeleteObject(int which)
+{
+ type[numobjects-1]=0;
+ rotation[numobjects-1]=0;
+ position[numobjects-1]=0;
+ scale[numobjects-1]=0;
+ friction[numobjects-1]=0;
+
+ numobjects--;
+}
+
+void Objects::MakeObject(int atype, XYZ where, float arotation, float ascale){
+ if((atype!=treeleavestype&&atype!=bushtype)||foliage==1){
+ scale[numobjects]=ascale;
+ if(atype==treeleavestype)scale[numobjects]+=abs((float)(Random()%100)/900)*ascale;
+
+ onfire[numobjects]=0;
+ flamedelay[numobjects]=0;
+ type[numobjects]=atype;
+
+ if(atype==firetype)onfire[numobjects]=1;
+
+ position[numobjects]=where;
+ if(atype==bushtype)position[numobjects].y=terrain.getHeight(position[numobjects].x,position[numobjects].z)-.3;
+ rotation[numobjects]=arotation;
+
+ rotxvel[numobjects]=0;
+ rotyvel[numobjects]=0;
+ rotx[numobjects]=0;
+ roty[numobjects]=0;
+
+ if(atype==boxtype)model[numobjects].loaddecal((char *)":Data:Models:Box.solid",0);
+ if(atype==cooltype)model[numobjects].loaddecal((char *)":Data:Models:Cool.solid",0);
+ if(atype==walltype)model[numobjects].loaddecal((char *)":Data:Models:Wall.solid",0);
+ if(atype==tunneltype)model[numobjects].loaddecal((char *)":Data:Models:Tunnel.solid",0);
+ if(atype==chimneytype)model[numobjects].loaddecal((char *)":Data:Models:Chimney.solid",0);
+ if(atype==spiketype)model[numobjects].load((char *)":Data:Models:Spike.solid",0);
+ if(atype==weirdtype)model[numobjects].loaddecal((char *)":Data:Models:Weird.solid",0);
+ if(atype==rocktype)model[numobjects].loaddecal((char *)":Data:Models:Rock.solid",0);
+ if(atype==treetrunktype)model[numobjects].load((char *)":Data:Models:Treetrunk.solid",0);
+ if(atype==treeleavestype)model[numobjects].load((char *)":Data:Models:Leaves.solid",0);
+ if(atype==bushtype)model[numobjects].load((char *)":Data:Models:Bush.solid",0);
+
+ if(atype==boxtype)friction[numobjects]=1.5;
+ if(atype==cooltype)friction[numobjects]=1.5;
+ if(atype==walltype)friction[numobjects]=1.5;
+ if(atype==platformtype)friction[numobjects]=1.5;
+ if(atype==tunneltype)friction[numobjects]=1.5;
+ if(atype==chimneytype)friction[numobjects]=1.5;
+ if(atype==rocktype)friction[numobjects]=.5;
+ if(atype==rocktype&&ascale>.5)friction[numobjects]=1.5;
+ if(atype==weirdtype)friction[numobjects]=1.5;
+ if(atype==spiketype)friction[numobjects]=.4;
+ if(atype==treetrunktype)friction[numobjects]=.4;
+ if(atype==treeleavestype)friction[numobjects]=0;
+
+ if(atype==platformtype){
+ model[numobjects].loaddecal((char *)":Data:Models:Platform.solid",0);
+ model[numobjects].Rotate(90,0,0);
+ }
+
+ if(type[numobjects]==boxtype||type[numobjects]==cooltype||type[numobjects]==spiketype||type[numobjects]==weirdtype||type[numobjects]==walltype||type[numobjects]==chimneytype||type[numobjects]==tunneltype||type[numobjects]==platformtype){
+ model[numobjects].ScaleTexCoords(scale[numobjects]*1.5);
+ }
+ if(type[numobjects]==rocktype){
+ model[numobjects].ScaleTexCoords(scale[numobjects]*3);
+ }
+ model[numobjects].flat=1;
+ if(atype==treetrunktype||atype==treeleavestype||atype==rocktype){
+ model[numobjects].flat=0;
+ }
+ model[numobjects].Scale(.3*scale[numobjects],.3*scale[numobjects],.3*scale[numobjects]);
+ model[numobjects].Rotate(90,1,1);
+ if(type[numobjects]==rocktype){
+ model[numobjects].Rotate(arotation*5,1,1);
+ }
+ model[numobjects].CalculateNormals(1);
+ model[numobjects].ScaleNormals(-1,-1,-1);
+
+ if(atype==treetrunktype&&position[numobjects].y<terrain.getHeight(position[numobjects].x,position[numobjects].z)+1){
+ if(detail==2)terrain.MakeDecal(shadowdecalpermanent,position[numobjects],2,.4,0);
+ }
+
+ if(atype==bushtype&&position[numobjects].y<terrain.getHeight(position[numobjects].x,position[numobjects].z)+1){
+ if(detail==2)terrain.MakeDecal(shadowdecalpermanent,position[numobjects],1,.4,0);
+ }
+
+ if(atype!=treeleavestype&&atype!=bushtype&&atype!=firetype)
+ terrain.AddObject(where+DoRotation(model[numobjects].boundingspherecenter,0,arotation,0),model[numobjects].boundingsphereradius,numobjects);
+
+ numobjects++;
+ }
+}
+
+void Objects::MakeObject(int atype, XYZ where, float arotation, float arotation2, float ascale){
+ if((atype!=treeleavestype&&atype!=bushtype)||foliage==1){
+ scale[numobjects]=ascale;
+ if(atype==treeleavestype)scale[numobjects]+=abs((float)(Random()%100)/900)*ascale;
+
+ onfire[numobjects]=0;
+ flamedelay[numobjects]=0;
+ type[numobjects]=atype;
+
+ if(atype==firetype)onfire[numobjects]=1;
+
+ position[numobjects]=where;
+ if(atype==bushtype)position[numobjects].y=terrain.getHeight(position[numobjects].x,position[numobjects].z)-.3;
+ /*if(atype==firetype){
+ if(position[numobjects].y<terrain.getHeight(position[numobjects].x,position[numobjects].z)-.3)
+ position[numobjects].y=terrain.getHeight(position[numobjects].x,position[numobjects].z)-.3;
+ }*/
+ rotation[numobjects]=arotation;
+ rotation2[numobjects]=arotation2;
+
+ rotxvel[numobjects]=0;
+ rotyvel[numobjects]=0;
+ rotx[numobjects]=0;
+ roty[numobjects]=0;
+
+ if(atype==boxtype)model[numobjects].loaddecal((char *)":Data:Models:Box.solid",0);
+ if(atype==cooltype)model[numobjects].loaddecal((char *)":Data:Models:Cool.solid",0);
+ if(atype==walltype)model[numobjects].loaddecal((char *)":Data:Models:Wall.solid",0);
+ if(atype==tunneltype)model[numobjects].loaddecal((char *)":Data:Models:Tunnel.solid",0);
+ if(atype==chimneytype)model[numobjects].loaddecal((char *)":Data:Models:Chimney.solid",0);
+ if(atype==spiketype)model[numobjects].load((char *)":Data:Models:Spike.solid",0);
+ if(atype==weirdtype)model[numobjects].loaddecal((char *)":Data:Models:Weird.solid",0);
+ if(atype==rocktype)model[numobjects].loaddecal((char *)":Data:Models:Rock.solid",0);
+ if(atype==treetrunktype)model[numobjects].load((char *)":Data:Models:Treetrunk.solid",0);
+ if(atype==treeleavestype)model[numobjects].load((char *)":Data:Models:Leaves.solid",0);
+ if(atype==bushtype)model[numobjects].load((char *)":Data:Models:Bush.solid",0);
+
+ if(atype==boxtype)friction[numobjects]=1.5;
+ if(atype==cooltype)friction[numobjects]=1.5;
+ if(atype==walltype)friction[numobjects]=1.5;
+ if(atype==platformtype)friction[numobjects]=1.5;
+ if(atype==tunneltype)friction[numobjects]=1.5;
+ if(atype==chimneytype)friction[numobjects]=1.5;
+ if(atype==rocktype)friction[numobjects]=.5;
+ if(atype==rocktype&&ascale>.5)friction[numobjects]=1.5;
+ if(atype==weirdtype)friction[numobjects]=1.5;
+ if(atype==spiketype)friction[numobjects]=.4;
+ if(atype==treetrunktype)friction[numobjects]=.4;
+ if(atype==treeleavestype)friction[numobjects]=0;
+
+ if(friction[numobjects]==1.5&&abs(arotation2)>5)friction[numobjects]=.5;
+
+ if(atype==platformtype){
+ model[numobjects].loaddecal((char *)":Data:Models:Platform.solid",0);
+ model[numobjects].Rotate(90,0,0);
+ }
+
+ if(type[numobjects]==boxtype||type[numobjects]==cooltype||type[numobjects]==spiketype||type[numobjects]==weirdtype||type[numobjects]==walltype||type[numobjects]==chimneytype||type[numobjects]==tunneltype||type[numobjects]==platformtype){
+ model[numobjects].ScaleTexCoords(scale[numobjects]*1.5);
+ }
+ if(type[numobjects]==rocktype){
+ model[numobjects].ScaleTexCoords(scale[numobjects]*3);
+ }
+ model[numobjects].flat=1;
+ if(atype==treetrunktype||atype==treeleavestype||atype==rocktype){
+ model[numobjects].flat=0;
+ }
+ model[numobjects].Scale(.3*scale[numobjects],.3*scale[numobjects],.3*scale[numobjects]);
+ model[numobjects].Rotate(90,1,1);
+ model[numobjects].Rotate(arotation2,0,0);
+ if(type[numobjects]==rocktype){
+ model[numobjects].Rotate(arotation*5,0,0);
+ }
+ model[numobjects].CalculateNormals(1);
+ model[numobjects].ScaleNormals(-1,-1,-1);
+
+ if(atype==treetrunktype&&position[numobjects].y<terrain.getHeight(position[numobjects].x,position[numobjects].z)+1){
+ if(detail==2)terrain.MakeDecal(shadowdecalpermanent,position[numobjects],2,.4,0);
+ }
+
+ if(atype==bushtype&&position[numobjects].y<terrain.getHeight(position[numobjects].x,position[numobjects].z)+1){
+ if(detail==2)terrain.MakeDecal(shadowdecalpermanent,position[numobjects],1,.4,0);
+ }
+
+ if(atype!=treeleavestype&&atype!=bushtype&&atype!=firetype)
+ terrain.AddObject(where+DoRotation(model[numobjects].boundingspherecenter,0,arotation,0),model[numobjects].boundingsphereradius,numobjects);
+
+ numobjects++;
+ }
+}
+
+void Objects::DoStuff()
+{
+ XYZ spawnpoint;
+ for(int i=0;i<numobjects;i++){
+ /*if(type[i]==firetype){
+ sprites.MakeSprite(weaponshinesprite, position[i],position[i]*0, 1,1,1, 5, 1);
+ }*/
+
+ if(type[i]==firetype)onfire[i]=1;
+ if(onfire[i]){
+ if(type[i]==bushtype)flamedelay[i]-=multiplier*3;
+ if(type[i]==firetype)flamedelay[i]-=multiplier*3;
+ if(type[i]==treeleavestype)flamedelay[i]-=multiplier*4;
+ while(flamedelay[i]<0&&onfire[i]){
+ flamedelay[i]+=.006;
+ if(type[i]==bushtype||type[i]==firetype){
+ spawnpoint.x=((float)(Random()%100))/30*scale[i];
+ spawnpoint.y=((float)(Random()%100)+60)/30*scale[i];
+ spawnpoint.z=0;
+ spawnpoint=DoRotation(spawnpoint,0,Random()%360,0);
+ spawnpoint+=position[i];
+ sprites.MakeSprite(flamesprite, spawnpoint,spawnpoint*0, 1,1,1, (.6+(float)abs(Random()%100)/200-.25)*5*scale[i], 1);
+ }
+ if(type[i]==treeleavestype){
+ spawnpoint.x=((float)(Random()%100))/80*scale[i];
+ spawnpoint.y=((float)(Random()%100)+80)/12*scale[i];
+ spawnpoint.z=0;
+ spawnpoint=DoRotation(spawnpoint,0,Random()%360,0);
+ spawnpoint+=position[i];
+ sprites.MakeSprite(flamesprite, spawnpoint,spawnpoint*0, 1,1,1, (.6+(float)abs(Random()%100)/200-.25)*6, 1);
+ }
+ }
+
+ }
+ }
+}
+
+void Objects::DoShadows()
+{
+ int i,j,k,l,todivide;
+ static float brightness, total;
+ static XYZ testpoint,testpoint2, terrainpoint,lightloc,col;
+ lightloc=light.location;
+ if(!skyboxtexture)lightloc=0;
+ lightloc.y+=10;
+ Normalise(&lightloc);
+ int patchx,patchz;
+
+ if(numobjects>0)
+ for(i=0;i<numobjects;i++){
+ if(type[i]!=treeleavestype&&type[i]!=treetrunktype&&type[i]!=bushtype&&type[i]!=firetype){
+ for(j=0;j<model[i].vertexNum;j++){
+ terrainpoint=position[i]+DoRotation(model[i].vertex[j]+model[i].normals[j]*.1,0,rotation[i],0);
+ //terrainpoint.y+=model[i].boundingsphereradius;
+ shadowed[i]=0;
+ patchx=terrainpoint.x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ patchz=terrainpoint.z/(terrain.size/subdivision*terrain.scale*terraindetail);
+ if(patchx>=0&&patchz>=0&&patchx<subdivision&&patchz<subdivision)
+ if(terrain.patchobjectnum[patchx][patchz])
+ for(k=0;k<terrain.patchobjectnum[patchx][patchz];k++){
+ l=terrain.patchobjects[patchx][patchz][k];
+ if(type[l]!=treetrunktype/*&&l!=i*/){
+ testpoint=terrainpoint;
+ testpoint2=terrainpoint+lightloc*50*(1-shadowed[i]);
+ if(model[l].LineCheck(&testpoint,&testpoint2,&col,&position[l],&rotation[l])!=-1){
+ shadowed[i]=1-(findDistance(&terrainpoint,&col)/50);
+ }
+ }
+ }
+ if(shadowed[i]>0){
+ col=model[i].normals[j]-DoRotation(lightloc*shadowed[i],0,-rotation[i],0);
+ Normalise(&col);
+ for(k=0;k<model[i].TriangleNum;k++){
+ if(model[i].Triangles[k].vertex[0]==j){
+ l=k*24;
+ model[i].vArray[l+2]=col.x;
+ model[i].vArray[l+3]=col.y;
+ model[i].vArray[l+4]=col.z;
+ }
+ if(model[i].Triangles[k].vertex[1]==j){
+ l=k*24;
+ model[i].vArray[l+10]=col.x;
+ model[i].vArray[l+11]=col.y;
+ model[i].vArray[l+12]=col.z;
+ }
+ if(model[i].Triangles[k].vertex[2]==j){
+ l=k*24;
+ model[i].vArray[l+18]=col.x;
+ model[i].vArray[l+19]=col.y;
+ model[i].vArray[l+20]=col.z;
+ }
+ }
+ }
+ }
+ }
+ shadowed[i]=0;
+ }
+}
+
+Objects::Objects()
+{
+ center = 0;
+ radius = 0;
+ numobjects = 0;
+ boxtextureptr = 0;
+ treetextureptr = 0;
+ bushtextureptr = 0;
+ rocktextureptr = 0;
+
+ memset(position, 0, sizeof(position));
+ memset(type, 0, sizeof(type));
+ memset(rotation, 0, sizeof(rotation));
+ memset(rotation2, 0, sizeof(rotation2));
+ memset(rotx, 0, sizeof(rotx));
+ memset(rotxvel, 0, sizeof(rotxvel));
+ memset(roty, 0, sizeof(roty));
+ memset(rotyvel, 0, sizeof(rotyvel));
+ memset(possible, 0, sizeof(possible));
+ memset(model, 0, sizeof(model));
+ memset(displaymodel, 0, sizeof(displaymodel));
+ memset(friction, 0, sizeof(friction));
+ memset(scale, 0, sizeof(scale));
+ memset(messedwith, 0, sizeof(messedwith));
+ memset(checked, 0, sizeof(checked));
+ memset(shadowed, 0, sizeof(shadowed));
+ memset(occluded, 0, sizeof(occluded));
+ memset(onfire, 0, sizeof(onfire));
+ memset(flamedelay, 0, sizeof(flamedelay));
+}
+
+Objects::~Objects()
+{
+ if (boxtextureptr) glDeleteTextures( 1, (const unsigned long *)&boxtextureptr );
+ if (treetextureptr) glDeleteTextures( 1, (const unsigned long *)&treetextureptr );
+ if (bushtextureptr) glDeleteTextures( 1, (const unsigned long *)&bushtextureptr );
+ if (rocktextureptr) glDeleteTextures( 1, (const unsigned long *)&rocktextureptr );
+};
--- /dev/null
+#ifndef _OBJECTS_H_
+#define _OBJECTS_H_
+
+#include "Quaternions.h"
+#include "gl.h"
+#include "TGALoader.h"
+#include "Quaternions.h"
+#include "Frustum.h"
+#include "Lights.h"
+#include "Models.h"
+#include "Terrain.h"
+#include "Sprites.h"
+#include <vector>
+//
+// Model Structures
+//
+
+#define max_objects 300
+
+#define boxtype 0
+#define weirdtype 1
+#define spiketype 2
+#define treetrunktype 3
+#define treeleavestype 4
+#define bushtype 5
+#define rocktype 6
+#define walltype 7
+#define chimneytype 8
+#define platformtype 9
+#define tunneltype 11
+#define cooltype 12
+#define firetype 13
+
+
+class Objects{
+public:
+ XYZ center;
+ float radius;
+ XYZ position[max_objects];
+ int type[max_objects];
+ float rotation[max_objects];
+ float rotation2[max_objects];
+ float rotx[max_objects];
+ float rotxvel[max_objects];
+ float roty[max_objects];
+ float rotyvel[max_objects];
+ int numobjects;
+ bool possible[max_objects];
+ Model model[max_objects];
+ Model displaymodel[max_objects];
+ float friction[max_objects];
+ float scale[max_objects];
+ float messedwith[max_objects];
+ float checked[max_objects];
+ GLuint boxtextureptr;
+ GLuint treetextureptr;
+ GLuint bushtextureptr;
+ GLuint rocktextureptr;
+ float shadowed[max_objects];
+ float occluded[max_objects];
+ bool checkcollide(XYZ startpoint, XYZ endpoint,int which);
+ bool onfire[max_objects];
+ float flamedelay[max_objects];
+
+ void SphereCheckPossible(XYZ *p1,float radius);
+ void DeleteObject(int which);
+ void MakeObject(int atype, XYZ where, float arotation, float ascale);
+ void MakeObject(int atype, XYZ where, float arotation, float arotation2, float ascale);
+ void Draw();
+ void DoShadows();
+ void DoStuff();
+
+ Objects();
+ ~Objects();
+};
+
+#endif
--- /dev/null
+#include "Game.h"
+#include "nommgr.h"
+
+extern bool buttons[3];
+extern float multiplier;
+extern float screenwidth,screenheight;
+extern float sps;
+extern float realmultiplier;
+extern int slomo;
+extern bool ismotionblur;
+extern float usermousesensitivity;
+extern int detail;
+extern bool floatjump;
+extern bool cellophane;
+extern int terraindetail;
+extern int texdetail;
+extern int bloodtoggle;
+extern bool osx;
+extern bool autoslomo;
+extern bool foliage;
+extern bool musictoggle;
+extern bool trilinear;
+extern float gamespeed;
+extern int difficulty;
+extern bool damageeffects;
+extern int numplayers;
+extern bool decals;
+extern bool invertmouse;
+extern bool texttoggle;
+extern bool ambientsound;
+extern bool mousejump;
+extern bool freeze;
+extern Person player[maxplayers];
+extern bool vblsync;
+extern bool stillloading;
+extern bool showpoints;
+extern bool alwaysblur;
+extern bool immediate;
+extern bool velocityblur;
+extern bool debugmode;
+extern int mainmenu;
+extern int kBitsPerPixel;
+extern float slomospeed;
+extern float slomofreq;
+extern float oldgamespeed;
+
+ #define kUseAGLFullScreenX 1
+ #define kUseFades 1
+
+// system includes ----------------------------------------------------------
+
+#ifdef __APPLE_CC__
+ #include "Carbon Include.h"
+ #include <Carbon/Carbon.h>
+
+ #include <DrawSprocket/DrawSprocket.h>
+ #include <AGL/agl.h>
+ #include <AGL/aglRenderers.h>
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glu.h>
+#else
+ #include <DrawSprocket.h>
+
+ #include <Devices.h>
+ #include <Dialogs.h>
+ #include <DriverServices.h>
+ #include <Events.h>
+ #include <Gestalt.h>
+ #include <LowMem.h>
+ #include <Sound.h>
+ #include <TextEdit.h>
+ #include <ToolUtils.h>
+ #include <Windows.h>
+
+ // profile
+ #include <Profiler.h>
+
+ #include "agl.h"
+ #include "gl.h"
+ #include "glu.h"
+#endif
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <Folders.h>
+#include <fstream.h>
+
+// project includes ---------------------------------------------------------
+
+#include "aglString.h"
+#include "MacInput.h"
+
+// functions (internal/private) ---------------------------------------------
+
+static UInt32 CheckMacOSX (void);
+void CToPStr (StringPtr outString, const char *inString);
+void ReportError (char * strError);
+OSStatus DSpDebugStr (OSStatus error);
+GLenum aglDebugStr (void);
+GLenum glDebugStr (void);
+
+CGrafPtr SetupDSpFullScreen (GDHandle hGD);
+void ShutdownDSp (CGrafPtr pDSpPort);
+
+AGLContext SetupAGL (GDHandle hGD, AGLDrawable win);
+AGLContext SetupAGLFullScreen (GDHandle display, short * pDepth, short * pWidth, short * pHeight);
+void CleanupAGL (AGLContext ctx);
+void DrawGL (Rect * pRectPort);
+
+void InitToolbox(void);
+void CreateGLWindow (void);
+Boolean SetUp (void);
+void DoMenu (SInt32 menuResult);
+void DoKey (SInt8 theKey, SInt8 theCode);
+void DoUpdate (void);
+
+pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData);
+EventLoopTimerUPP GetTimerUPP (void);
+static Boolean RunningOnCarbonX(void);
+
+void DoEvent (void);
+void CleanUp (void);
+
+// profile wrappers
+Boolean WaitNextEventWrapper (EventMask eventMask, EventRecord *theEvent, unsigned long sleep,RgnHandle mouseRgn);
+OSStatus DSpProcessEventWrapper (EventRecord *inEvent, Boolean *outEventWasProcessed);
+void UpdateWrapper (EventRecord *theEvent);
+
+// statics/globals (internal only) ------------------------------------------
+
+Point delta;
+
+// Menu defs
+enum
+{
+ kMenuApple = 128,
+ kMenuFile = 129,
+
+ kAppleAbout = 1,
+ kFileQuit = 1
+};
+
+enum
+{
+ kForegroundSleep = 10,
+ kBackgroundSleep = 10000
+};
+EventLoopTimerRef gTimer = NULL;
+
+int kContextWidth;
+int kContextHeight;
+
+const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
+
+NumVersion gVersionDSp;
+DSpContextAttributes gContextAttributes;
+DSpContextReference gContext = 0;
+extern AGLContext gaglContext;
+GLuint gFontList;
+char gcstrMode [256] = "";
+
+AGLDrawable gpDSpPort = NULL; // will be NULL for full screen under X
+Rect gRectPort = {0, 0, 0, 0};
+
+UInt32 gSleepTime = kForegroundSleep;
+Boolean gDone = false, gfFrontProcess = true;
+
+Game game;
+
+// profile
+#if __profile__
+OSErr gProfErr = noErr;
+#endif
+
+#pragma mark -
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// are we running on Mac OS X
+// returns 0 if < Mac OS X or version number of Mac OS X (10.0 for GM)
+
+static UInt32 CheckMacOSX (void)
+{
+ UInt32 response;
+
+ if ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x01000))
+ return response;
+ else
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// Copy C string to Pascal string
+
+void CToPStr (StringPtr outString, const char *inString)
+{
+ unsigned char x = 0;
+ do
+ *(((char*)outString) + x + 1) = *(inString + x++);
+ while ((*(inString + x) != 0) && (x < 256));
+ *((char*)outString) = (char) x;
+}
+
+// --------------------------------------------------------------------------
+
+void ReportError (char * strError)
+{
+ char errMsgCStr [256];
+ Str255 strErr;
+
+ sprintf (errMsgCStr, "%s", strError);
+
+ // out as debug string
+ CToPStr (strErr, errMsgCStr);
+ DebugStr (strErr);
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+OSStatus DSpDebugStr (OSStatus error)
+{
+ switch (error)
+ {
+ case noErr:
+ break;
+ case kDSpNotInitializedErr:
+ ReportError ("DSp Error: Not initialized");
+ break;
+ case kDSpSystemSWTooOldErr:
+ ReportError ("DSp Error: system Software too old");
+ break;
+ case kDSpInvalidContextErr:
+ ReportError ("DSp Error: Invalid context");
+ break;
+ case kDSpInvalidAttributesErr:
+ ReportError ("DSp Error: Invalid attributes");
+ break;
+ case kDSpContextAlreadyReservedErr:
+ ReportError ("DSp Error: Context already reserved");
+ break;
+ case kDSpContextNotReservedErr:
+ ReportError ("DSp Error: Context not reserved");
+ break;
+ case kDSpContextNotFoundErr:
+ ReportError ("DSp Error: Context not found");
+ break;
+ case kDSpFrameRateNotReadyErr:
+ ReportError ("DSp Error: Frame rate not ready");
+ break;
+ case kDSpConfirmSwitchWarning:
+// ReportError ("DSp Warning: Must confirm switch"); // removed since it is just a warning, add back for debugging
+ return 0; // don't want to fail on this warning
+ break;
+ case kDSpInternalErr:
+ ReportError ("DSp Error: Internal error");
+ break;
+ case kDSpStereoContextErr:
+ ReportError ("DSp Error: Stereo context");
+ break;
+ }
+ return error;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// if error dump agl errors to debugger string, return error
+
+GLenum aglDebugStr (void)
+{
+ GLenum err = aglGetError();
+ if (AGL_NO_ERROR != err)
+ ReportError ((char *)aglErrorString(err));
+ return err;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// if error dump agl errors to debugger string, return error
+
+GLenum glDebugStr (void)
+{
+ GLenum err = glGetError();
+ if (GL_NO_ERROR != err)
+ ReportError ((char *)gluErrorString(err));
+ return err;
+}
+
+#pragma mark -
+//-----------------------------------------------------------------------------------------------------------------------
+
+// Set up DSp screen on graphics device requested
+// side effect: sets both gpDSpWindow and gpPort
+
+CGrafPtr SetupDSpFullScreen (GDHandle hGD)
+{
+ DSpContextAttributes foundAttributes;
+ DisplayIDType displayID = NULL;
+
+ if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpGetVersion)
+ {
+ ReportError ("DrawSprocket not installed.");
+ return NULL;
+ }
+ else
+ gVersionDSp = DSpGetVersion ();
+
+ if ((gVersionDSp.majorRev == 0x01) && (gVersionDSp.minorAndBugRev < 0x99))
+ {
+ // this version of DrawSprocket is not completely functional on Mac OS X
+ if (CheckMacOSX ())
+ {
+ ReportError ("DrawSprocket 1.99 or greate required on Mac OS X, please update to at least Mac OS X 10.1.");
+ return NULL;
+ }
+ }
+
+ // Note: DSp < 1.7.3 REQUIRES the back buffer attributes even if only one buffer is required
+ memset(&gContextAttributes, 0, sizeof (DSpContextAttributes));
+ gContextAttributes.displayWidth = kContextWidth;
+ gContextAttributes.displayHeight = kContextHeight;
+ gContextAttributes.colorNeeds = kDSpColorNeeds_Require;
+ gContextAttributes.displayBestDepth = kBitsPerPixel;
+ gContextAttributes.backBufferBestDepth = kBitsPerPixel;
+ gContextAttributes.displayDepthMask = kDSpDepthMask_All;
+ gContextAttributes.backBufferDepthMask = kDSpDepthMask_All;
+ gContextAttributes.pageCount = 1; // only the front buffer is needed
+
+ screenwidth=kContextWidth;
+ screenheight=kContextHeight;
+
+ DMGetDisplayIDByGDevice (hGD, &displayID, true);
+
+ if (noErr != DSpDebugStr (DSpFindBestContextOnDisplayID (&gContextAttributes, &gContext, displayID)))
+ {
+ ReportError ("DSpFindBestContext() had an error.");
+ return NULL;
+ }
+
+ if (noErr != DSpDebugStr (DSpContext_GetAttributes (gContext, &foundAttributes))) // see what we actually found
+ {
+ ReportError ("DSpContext_GetAttributes() had an error.");
+ return NULL;
+ }
+
+ // reset width and height to full screen and handle our own centering
+ // HWA will not correctly center less than full screen size contexts
+ gContextAttributes.displayWidth = foundAttributes.displayWidth;
+ gContextAttributes.displayHeight = foundAttributes.displayHeight;
+ gContextAttributes.pageCount = 1; // only the front buffer is needed
+ gContextAttributes.contextOptions = 0 | kDSpContextOption_DontSyncVBL; // no page flipping and no VBL sync needed
+
+ DSpSetBlankingColor(&rgbBlack);
+
+ if (noErr != DSpDebugStr (DSpContext_Reserve ( gContext, &gContextAttributes))) // reserve our context
+ {
+ ReportError ("DSpContext_Reserve() had an error.");
+ return NULL;
+ }
+
+ HideCursor ();
+
+ if (noErr != DSpDebugStr (DSpContext_SetState (gContext, kDSpContextState_Active))) // activate our context
+ {
+ ReportError ("DSpContext_SetState() had an error.");
+ return NULL;
+ }
+
+
+ if ((CheckMacOSX ()) && !((gVersionDSp.majorRev > 0x01) || ((gVersionDSp.majorRev == 0x01) && (gVersionDSp.minorAndBugRev >= 0x99))))// DSp should be supported in version after 1.98
+ {
+ ReportError ("Mac OS X with DSp < 1.99 does not support DrawSprocket for OpenGL full screen");
+ return NULL;
+ }
+ else if (CheckMacOSX ()) // DSp should be supported in versions 1.99 and later
+ {
+ CGrafPtr pPort;
+ // use DSp's front buffer on Mac OS X
+ if (noErr != DSpDebugStr (DSpContext_GetFrontBuffer (gContext, &pPort)))
+ {
+ ReportError ("DSpContext_GetFrontBuffer() had an error.");
+ return NULL;
+ }
+ // there is a problem in Mac OS X 10.0 GM CoreGraphics that may not size the port pixmap correctly
+ // this will check the vertical sizes and offset if required to fix the problem
+ // this will not center ports that are smaller then a particular resolution
+ {
+ long deltaV, deltaH;
+ Rect portBounds;
+ PixMapHandle hPix = GetPortPixMap (pPort);
+ Rect pixBounds = (**hPix).bounds;
+ GetPortBounds (pPort, &portBounds);
+ deltaV = (portBounds.bottom - portBounds.top) - (pixBounds.bottom - pixBounds.top) +
+ (portBounds.bottom - portBounds.top - kContextHeight) / 2;
+ deltaH = -(portBounds.right - portBounds.left - kContextWidth) / 2;
+ if (deltaV || deltaH)
+ {
+ GrafPtr pPortSave;
+ GetPort (&pPortSave);
+ SetPort ((GrafPtr)pPort);
+ // set origin to account for CG offset and if requested drawable smaller than screen rez
+ SetOrigin (deltaH, deltaV);
+ SetPort (pPortSave);
+ }
+ }
+ return pPort;
+ }
+ else // Mac OS 9 or less
+ {
+ WindowPtr pWindow;
+ Rect rectWin;
+ RGBColor rgbSave;
+ GrafPtr pGrafSave;
+ // create a new window in our context
+ // note: OpenGL is expecting a window so it can enumerate the devices it spans,
+ // center window in our context's gdevice
+ rectWin.top = (short) ((**hGD).gdRect.top + ((**hGD).gdRect.bottom - (**hGD).gdRect.top) / 2); // h center
+ rectWin.top -= (short) (kContextHeight / 2);
+ rectWin.left = (short) ((**hGD).gdRect.left + ((**hGD).gdRect.right - (**hGD).gdRect.left) / 2); // v center
+ rectWin.left -= (short) (kContextWidth / 2);
+ rectWin.right = (short) (rectWin.left + kContextWidth);
+ rectWin.bottom = (short) (rectWin.top + kContextHeight);
+
+ pWindow = NewCWindow (NULL, &rectWin, "\p", 0, plainDBox, (WindowPtr)-1, 0, 0);
+
+ // paint back ground black before fade in to avoid white background flash
+ ShowWindow(pWindow);
+ GetPort (&pGrafSave);
+ SetPortWindowPort (pWindow);
+ GetForeColor (&rgbSave);
+ RGBForeColor (&rgbBlack);
+ {
+ Rect paintRect;
+ GetWindowPortBounds (pWindow, &paintRect);
+ PaintRect (&paintRect);
+ }
+ RGBForeColor (&rgbSave); // ensure color is reset for proper blitting
+ SetPort (pGrafSave);
+ return (GetWindowPort (pWindow));
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// clean up DSp
+
+void ShutdownDSp (CGrafPtr pDSpPort)
+{
+ if ((NULL != pDSpPort) && !CheckMacOSX ())
+ DisposeWindow (GetWindowFromPort (pDSpPort));
+ DSpContext_SetState( gContext, kDSpContextState_Inactive);
+ DSpContext_Release (gContext);
+}
+
+#pragma mark -
+//-----------------------------------------------------------------------------------------------------------------------
+
+// OpenGL Setup
+
+
+AGLContext SetupAGL (GDHandle hGD, AGLDrawable drawable)
+{
+ GLint attrib[64];
+
+ AGLPixelFormat fmt;
+ AGLContext ctx;
+
+// different possible pixel format choices for different renderers
+// basics requirements are RGBA and double buffer
+// OpenGLz will select acclerated context if available
+
+ short i = 0;
+ attrib [i++] = AGL_RGBA; // red green blue and alpha
+ attrib [i++] = AGL_DOUBLEBUFFER; // double buffered
+ attrib [i++] = AGL_DEPTH_SIZE;
+ attrib [i++] = 8;
+ attrib [i++] = AGL_ACCELERATED; // HWA pixel format only
+ attrib [i++] = AGL_NONE;
+
+ if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL
+ {
+ ReportError ("OpenGL not installed");
+ return NULL;
+ }
+
+ if (hGD)
+ fmt = aglChoosePixelFormat (&hGD, 1, attrib); // get an appropriate pixel format
+ else
+ fmt = aglChoosePixelFormat(NULL, 0, attrib); // get an appropriate pixel format
+ aglDebugStr ();
+ if (NULL == fmt)
+ {
+ ReportError("Could not find valid pixel format");
+ return NULL;
+ }
+
+ ctx = aglCreateContext (fmt, NULL); // Create an AGL context
+ aglDebugStr ();
+ if (NULL == ctx)
+ {
+ ReportError ("Could not create context");
+ return NULL;
+ }
+
+ if (!aglSetDrawable (ctx, drawable)) // attach the window to the context
+ {
+ ReportError ("SetDrawable failed");
+ aglDebugStr ();
+ return NULL;
+ }
+
+
+ if (!aglSetCurrentContext (ctx)) // make the context the current context
+ {
+ aglDebugStr ();
+ aglSetDrawable (ctx, NULL);
+ return NULL;
+ }
+
+ aglDestroyPixelFormat(fmt); // pixel format is no longer needed
+
+ return ctx;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// OpenGL Setup
+
+AGLContext SetupAGLFullScreen (GDHandle display, short * pDepth, short * pWidth, short * pHeight)
+{
+ //GLint attrib[64];
+ GLint attrib[] ={AGL_RGBA, AGL_DOUBLEBUFFER,AGL_DEPTH_SIZE, 16, AGL_FULLSCREEN,AGL_ALL_RENDERERS, AGL_NONE};
+
+ AGLPixelFormat fmt;
+ AGLContext ctx;
+
+
+ if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL
+ {
+ ReportError ("OpenGL not installed");
+ return NULL;
+ }
+
+ fmt = aglChoosePixelFormat(&display, 1, attrib); // this may fail if looking for acclerated across multiple monitors
+ if (NULL == fmt)
+ {
+ ReportError("Could not find valid pixel format");
+ aglDebugStr ();
+ return NULL;
+ }
+
+ ctx = aglCreateContext (fmt, NULL); // Create an AGL context
+ if (NULL == ctx)
+ {
+ ReportError ("Could not create context");
+ aglDebugStr ();
+ return NULL;
+ }
+
+ if (!aglSetFullScreen (ctx, *pWidth, *pHeight, 60, 0))
+ {
+ ReportError ("SetFullScreen failed");
+ aglDebugStr ();
+ return NULL;
+ }
+
+ if (!aglSetCurrentContext (ctx)) // make the context the current context
+ {
+ ReportError ("SetCurrentContext failed");
+ aglDebugStr ();
+ aglSetDrawable (ctx, NULL); // turn off full screen
+ return NULL;
+ }
+
+ aglDestroyPixelFormat(fmt); // pixel format is no longer needed
+
+ return ctx;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// OpenGL Cleanup
+
+void CleanupAGL(AGLContext ctx)
+{
+ aglSetDrawable (ctx, NULL);
+ aglSetCurrentContext (NULL);
+ aglDestroyContext (ctx);
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// OpenGL Drawing
+
+void DrawGL (Rect * pRectPort)
+{
+ if (gaglContext == 0)
+ return;
+ aglSetCurrentContext (gaglContext); // ensure our context is current prior to drawing
+
+ {
+ GLint width = pRectPort->right - pRectPort->left;
+ GLint height = pRectPort->bottom - pRectPort->top;
+ screenwidth=width;
+ screenheight=height;
+ /* glViewport ((width - (width * 1)) / 2, (height - (height * 1)) / 2,
+ width * 1, height * 1);*/
+ }
+
+ game.DrawGLScene();
+
+
+ //glDebugStr ();
+
+ // draw info
+ /*{
+ GLint matrixMode;
+ glViewport (0, 0, pRectPort->right - pRectPort->left, pRectPort->bottom - pRectPort->top);
+ glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
+ glMatrixMode (GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity ();
+ glMatrixMode (GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity ();
+ glScalef (2.0 / (pRectPort->right - pRectPort->left), -2.0 / (pRectPort->bottom - pRectPort->top), 1.0);
+ glTranslatef (-(pRectPort->right - pRectPort->left) / 2.0, -(pRectPort->bottom - pRectPort->top) / 2.0, 0.0);
+ glColor3f (1.0, 1.0, 1.0);
+ glRasterPos3d (10, 12, 0);
+ DrawFrameRate (gFontList);
+ glRasterPos3d (10, 24, 0);
+ DrawCStringGL (gcstrMode, gFontList);
+ glRasterPos3d (10, (pRectPort->bottom - pRectPort->top) - 15, 0);
+ DrawCStringGL ((char*) glGetString (GL_VENDOR), gFontList);
+ glRasterPos3d (10, (pRectPort->bottom - pRectPort->top) - 3, 0);
+ DrawCStringGL ((char*) glGetString (GL_RENDERER), gFontList);
+ static char aChar[256] = "";
+ sprintf (aChar, " Mac OS X: %d", RunningOnCarbonX());
+ DrawCStringGL (aChar, gFontList);
+ glPopMatrix();
+ glMatrixMode (GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode (matrixMode);
+ }*/
+ //glDebugStr ();
+ //aglSwapBuffers(gaglContext); // send swap command
+}
+
+#pragma mark -
+//-----------------------------------------------------------------------------------------------------------------------
+
+static pascal OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, SInt32 refcon )
+{
+ #pragma unused (appleEvt, reply, refcon)
+ //gDone = true;
+ game.tryquit=1;
+ return false;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+void InitToolbox(void)
+{
+ OSErr err;
+ long response;
+ MenuHandle menu;
+
+ InitCursor();
+
+// profile
+#if __profile__
+// prototype:
+// ProfilerInit (collection method, time base, num funcs, stack depth)
+ // default call
+ gProfErr = ProfilerInit (collectDetailed, bestTimeBase, 20, 10); // set up profiling
+ // something that you may need to do (may need more memory)
+// gProfErr = ProfilerInit (collectSummary, bestTimeBase, 1000, 100); // set up profiling
+// Note: application will likely run slower, but still should be useful info
+ if (noErr == gProfErr)
+ ProfilerSetStatus(FALSE);
+#endif
+
+ // Init Menus
+ menu = NewMenu (kMenuApple, "\p\024"); // new apple menu
+ InsertMenu (menu, 0); // add menu to end
+
+ menu = NewMenu (kMenuFile, "\pFile"); // new menu
+ InsertMenu (menu, 0); // add menu to end
+
+ // insert application menus here
+
+ // add quit if not under Mac OS X
+ err = Gestalt (gestaltMenuMgrAttr, &response);
+ if ((err == noErr) && !(response & gestaltMenuMgrAquaLayoutMask))
+ AppendMenu (menu, "\pQuit/Q"); // add quit
+
+ DrawMenuBar();
+ err = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false );
+ if (err != noErr)
+ ExitToShell();
+}
+
+// --------------------------------------------------------------------------
+
+static Point gMidPoint;
+
+Boolean SetUp (void)
+{
+ char string[10];
+
+ SetQDGlobalsRandomSeed(TickCount());
+
+ osx = 0;
+ if(CheckMacOSX ())osx = 1;
+ ifstream ipstream(":Data:config.txt");
+ detail=1;
+ ismotionblur=0;
+ usermousesensitivity=1;
+ kContextWidth=640;
+ kContextHeight=480;
+ kBitsPerPixel = 32;
+ floatjump=0;
+ cellophane=0;
+ texdetail=4;
+ autoslomo=1;
+ decals=1;
+ invertmouse=0;
+ bloodtoggle=0;
+ terraindetail=2;
+ foliage=1;
+ musictoggle=1;
+ trilinear=1;
+ gamespeed=1;
+ difficulty=1;
+ damageeffects=0;
+ texttoggle=1;
+ alwaysblur=0;
+ showpoints=0;
+ immediate=0;
+ velocityblur=0;
+ slomospeed=0.25;
+ slomofreq=8012;
+
+ game.crouchkey=MAC_SHIFT_KEY;
+ game.jumpkey=MAC_SPACE_KEY;
+ game.leftkey=MAC_A_KEY;
+ game.forwardkey=MAC_W_KEY;
+ game.backkey=MAC_S_KEY;
+ game.rightkey=MAC_D_KEY;
+ game.drawkey=MAC_E_KEY;
+ game.throwkey=MAC_Q_KEY;
+ game.attackkey=MAC_MOUSEBUTTON1;
+ game.chatkey=MAC_T_KEY;
+ numplayers=1;
+ ambientsound=1;
+ vblsync=0;
+ debugmode=0;
+ if(!ipstream) {
+ ofstream opstream(":Data:config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << kContextWidth;
+ opstream << "\nScreenheight:\n";
+ opstream << kContextHeight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << detail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ opstream << gamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(game.forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(game.backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(game.leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(game.rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(game.jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(game.crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(game.drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(game.throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(game.attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(game.chatkey);
+ opstream.close();
+ }
+ if(ipstream){
+ ipstream.ignore(256,'\n');
+ ipstream >> kContextWidth;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> kContextHeight;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> usermousesensitivity;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> ismotionblur;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> detail;
+ if(detail!=0)kBitsPerPixel=32;
+ else kBitsPerPixel=16;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> floatjump;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> mousejump;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> ambientsound;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> bloodtoggle;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> autoslomo;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> foliage;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> musictoggle;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> trilinear;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> decals;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> invertmouse;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> gamespeed;
+ oldgamespeed=gamespeed;
+ if(oldgamespeed==0){
+ gamespeed=1;
+ oldgamespeed=1;
+ }
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> difficulty;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> damageeffects;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> texttoggle;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> debugmode;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> vblsync;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> showpoints;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> alwaysblur;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> immediate;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> velocityblur;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.forwardkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.backkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.leftkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.rightkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.jumpkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.crouchkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.drawkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.throwkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.attackkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.chatkey=CharToKey(string);
+ ipstream.close();
+
+ if(detail>2)detail=2;
+ if(detail<0)detail=0;
+ if(screenwidth>3000)screenwidth=640;
+ if(screenwidth<0)screenwidth=640;
+ if(screenheight>3000)screenheight=480;
+ if(screenheight<0)screenheight=480;
+ }
+
+
+ if(vblsync){
+ GLint swapInt = 1;
+ aglSetInteger(gaglContext, AGL_SWAP_INTERVAL, &swapInt);
+ }
+
+ if(kBitsPerPixel!=32&&kBitsPerPixel!=16){
+ kBitsPerPixel=16;
+ }
+
+
+ GDHandle hGD, hTargetDevice = NULL;
+ short numDevices = 0;
+ short fNum = 0;
+ short whichDevice = 0; // number of device to try (0 = 1st device)
+
+ InitToolbox ();
+
+ gpDSpPort = NULL;
+ gaglContext = 0;
+
+ // check for DSp
+ if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpStartup)
+ ReportError ("DSp not installed");
+
+ if (noErr != DSpDebugStr (DSpStartup()))
+ return NULL;
+// DSpSetDebugMode (true);
+#if defined kUseFades
+ DSpDebugStr (DSpContext_FadeGammaOut (NULL, NULL)); // fade display, remove for debug
+#endif
+
+ hGD = DMGetFirstScreenDevice (true); // check number of screens
+ hTargetDevice = hGD; // default to first device
+ do
+ {
+ if (numDevices == whichDevice)
+ hTargetDevice = hGD; // if device number matches
+ numDevices++;
+ hGD = DMGetNextScreenDevice (hGD, true);
+ }
+ while (hGD);
+
+#if defined (kUseAGLFullScreenX)
+ if (CheckMacOSX ()) // Try AGL full screen on Mac OS X
+ {
+ short depth = kBitsPerPixel, width = kContextWidth, height = kContextHeight;
+ gaglContext = SetupAGLFullScreen (hTargetDevice, &depth, &width, &height); // Setup the OpenGL context
+ SetRect (&gRectPort, 0, 0, width, height); // l, t, r, b
+ sprintf (gcstrMode, "AGL Full Screen: %d x %d x %d", width, height, depth);
+ }
+#endif
+ if (!gaglContext) //try DSp
+ {
+ if (NULL != (gpDSpPort = SetupDSpFullScreen (hTargetDevice))) // Setup DSp for OpenGL sets hTargetDeviceto device actually used
+ {
+ GetPortBounds (gpDSpPort, &gRectPort);
+ sprintf (gcstrMode, "DrawSprocket Full Screen: %d x %d x %d", gRectPort.right - gRectPort.left, gRectPort.bottom - gRectPort.top, (**(**hTargetDevice).gdPMap).pixelSize);
+ gaglContext = SetupAGL (hTargetDevice, gpDSpPort);
+ }
+ }
+ if (gaglContext)
+ {
+ GetFNum("\pMonaco", &fNum); // build font
+ gFontList = BuildFontGL (gaglContext, fNum, normal, 9);
+ //InstallEventLoopTimer (GetCurrentEventLoop(), 0, 0.0001, GetTimerUPP (), 0, &gTimer);
+ }
+
+ //gMidPoint.h = (gRectPort.left + gRectPort.right)/2;
+ //gMidPoint.v = (gRectPort.top + gRectPort.bottom)/2;
+ gMidPoint.h = 200;
+ gMidPoint.v = 200;
+ GLint swapInt = 1;
+ //aglSetInteger(gaglContext, AGL_SWAP_INTERVAL, &swapInt);
+
+#if defined kUseFades
+ DSpDebugStr (DSpContext_FadeGammaIn (NULL, NULL));
+#endif
+
+
+ HideCursor();
+
+
+ GLint width = gRectPort.right - gRectPort.left;
+ GLint height = gRectPort.bottom - gRectPort.top;
+ screenwidth=width;
+ screenheight=height;
+
+ game.newdetail=detail;
+ game.newscreenwidth=screenwidth;
+ game.newscreenheight=screenheight;
+
+ game.InitGame();
+
+ if (gaglContext)
+ return true;
+ else
+ return false;
+
+}
+
+static Boolean RunningOnCarbonX(void)
+{
+ static Boolean first = true;
+ static Boolean result = false;
+
+ if (first)
+ {
+ UInt32 response;
+
+ first = false;
+
+ result = (Gestalt(gestaltSystemVersion,
+ (SInt32 *) &response) == noErr)
+ && (response >= 0x01000);
+ }
+ return result;
+}
+
+static OSStatus LoadFrameworkBundle(CFStringRef pFrameworkCFStrRef, CFBundleRef *pFrameworkCFBndlRef)
+{
+ OSStatus err;
+ FSRef frameworksFolderRef;
+ CFURLRef baseURL;
+ CFURLRef bundleURL;
+
+ if (nil == pFrameworkCFBndlRef) return paramErr;
+
+ *pFrameworkCFBndlRef = nil;
+
+ baseURL = nil;
+ bundleURL = nil;
+
+ err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
+ if (err == noErr) {
+ baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
+ if (baseURL == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, pFrameworkCFStrRef, false);
+ if (bundleURL == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ *pFrameworkCFBndlRef = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
+ if (*pFrameworkCFBndlRef == nil) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+ if (err == noErr) {
+ if ( ! CFBundleLoadExecutable( *pFrameworkCFBndlRef ) ) {
+ err = coreFoundationUnknownErr;
+ }
+ }
+
+ // Clean up.
+
+ if (err != noErr && *pFrameworkCFBndlRef != nil) {
+ CFRelease(*pFrameworkCFBndlRef);
+ *pFrameworkCFBndlRef = nil;
+ }
+ if (bundleURL != nil) {
+ CFRelease(bundleURL);
+ }
+ if (baseURL != nil) {
+ CFRelease(baseURL);
+ }
+
+ return err;
+}
+
+
+
+static CFragConnectionID gCFragConnectionID = 0;
+
+typedef pascal OSErr (*CDM_NewDeviceProcPtr)(CursorDevicePtr * ourDevice);
+
+static OSErr MyCursorDeviceNewDevice(CursorDevicePtr * ourDevice)
+{
+ static CDM_NewDeviceProcPtr sCDM_NewDeviceProcPtr = nil;
+ OSStatus anErr = noErr;
+
+ if (nil == ourDevice) return paramErr;
+
+ if (!RunningOnCarbonX())
+ {
+ if (!sCDM_NewDeviceProcPtr)
+ {
+ if (!gCFragConnectionID)
+ {
+ Ptr mainAddr;
+ Str255 errName;
+
+ anErr = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch,
+ kFindCFrag, &gCFragConnectionID, &mainAddr, errName);
+ if (noErr != anErr) return anErr;
+ }
+
+ if (gCFragConnectionID)
+ {
+ CFragSymbolClass symClass;
+
+ anErr = FindSymbol(gCFragConnectionID, "\pCrsrDevNewDevice",
+ (Ptr*) &sCDM_NewDeviceProcPtr, &symClass);
+ if (noErr != anErr) return anErr;
+ }
+ }
+ if (sCDM_NewDeviceProcPtr)
+ anErr = (*sCDM_NewDeviceProcPtr)(ourDevice);
+ else
+ anErr = paramErr;
+ }
+
+ return anErr;
+}
+
+typedef pascal OSErr (*CDM_CursorDeviceMoveToProcPtr)(
+ CursorDevicePtr ourDevice,
+ long absX,
+ long absY);
+
+typedef UInt32 (*CGWarpMouseCursorPositionProcPtr)(CGPoint newCursorPosition);
+typedef UInt32 (*CGSetLocalEventsSuppressionIntervalProcPtr)(double pSeconds);
+
+static OSErr MyCursorDeviceMoveTo( CursorDevicePtr ourDevice,
+ long absX,
+ long absY)
+{
+ OSStatus anErr = noErr;
+
+ if (RunningOnCarbonX())
+ {
+ static CGWarpMouseCursorPositionProcPtr sCGWarpMouseCursorPositionProcPtr = nil;
+
+ if (nil == sCGWarpMouseCursorPositionProcPtr)
+ {
+ CFBundleRef tCFBundleRef;
+
+ anErr = LoadFrameworkBundle(CFSTR("ApplicationServices.framework"), &tCFBundleRef);
+
+ if (noErr == anErr)
+ {
+ CGSetLocalEventsSuppressionIntervalProcPtr tCGSetLocalEventsSuppressionIntervalProcPtr = nil;
+
+ sCGWarpMouseCursorPositionProcPtr = (CGWarpMouseCursorPositionProcPtr)
+ CFBundleGetFunctionPointerForName( tCFBundleRef, CFSTR("CGWarpMouseCursorPosition") );
+ if (nil == sCGWarpMouseCursorPositionProcPtr)
+ anErr = cfragNoSymbolErr;
+
+ tCGSetLocalEventsSuppressionIntervalProcPtr = (CGSetLocalEventsSuppressionIntervalProcPtr)
+ CFBundleGetFunctionPointerForName(tCFBundleRef,CFSTR("CGSetLocalEventsSuppressionInterval"));
+ if (nil != tCGSetLocalEventsSuppressionIntervalProcPtr)
+ (*tCGSetLocalEventsSuppressionIntervalProcPtr)(0.0f);
+ }
+ }
+
+ if (nil != sCGWarpMouseCursorPositionProcPtr)
+ {
+ CGPoint tCGPoint;
+
+ tCGPoint.x = absX;
+ tCGPoint.y = absY;
+
+ (*sCGWarpMouseCursorPositionProcPtr)(tCGPoint);
+ }
+ }
+ else
+ {
+ static CDM_CursorDeviceMoveToProcPtr sCDM_CursorDeviceMoveToProcPtr = nil;
+
+ if (!ourDevice) return paramErr;
+
+ if (!sCDM_CursorDeviceMoveToProcPtr)
+ {
+ if (!gCFragConnectionID)
+ {
+ Ptr mainAddr;
+ Str255 errName;
+
+ anErr = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch,
+ kFindCFrag, &gCFragConnectionID, &mainAddr, errName);
+ if (noErr != anErr) return anErr;
+ }
+
+ if (gCFragConnectionID)
+ {
+ CFragSymbolClass symClass;
+
+ anErr = FindSymbol(gCFragConnectionID, "\pCrsrDevMoveTo",
+ (Ptr*) &sCDM_CursorDeviceMoveToProcPtr, &symClass);
+ if (noErr != anErr) return anErr;
+ }
+ }
+ if (sCDM_CursorDeviceMoveToProcPtr)
+ anErr = (*sCDM_CursorDeviceMoveToProcPtr)(ourDevice,absX,absY);
+ else
+ anErr = paramErr;
+ }
+
+ return anErr;
+}
+
+static void DoMouse(void)
+{
+ static CursorDevicePtr virtualCursorDevicePtr = nil;
+ OSStatus anErr = noErr;
+
+ HideCursor();
+
+ if (nil == virtualCursorDevicePtr)
+ anErr = MyCursorDeviceNewDevice(&virtualCursorDevicePtr);
+
+ {
+ static Point lastMouse = {-1,-1};
+ Point globalMouse;
+
+ GetGlobalMouse(&globalMouse);
+
+ if (EqualPt(lastMouse, globalMouse))
+ {
+ game.deltah=0;
+ game.deltav=0;
+ }
+
+ if (!EqualPt(lastMouse, globalMouse))
+ {
+ static Point virtualMouse = {0,0};
+ delta = globalMouse;
+
+ SubPt(lastMouse, &delta);
+ GetGlobalMouse(&lastMouse);
+ //AddPt(delta, &virtualMouse);
+
+ if(mainmenu||(abs(delta.h)<10*realmultiplier*1000&&abs(delta.v)<10*realmultiplier*1000)){
+ game.deltah=delta.h*usermousesensitivity;
+ game.deltav=delta.v*usermousesensitivity;
+ game.mousecoordh=globalMouse.h;
+ game.mousecoordv=globalMouse.v;
+ }
+#if 1
+ //printf("\nMouse Moved: {%d,%d}.",globalMouse.h,globalMouse.v);
+ //printf("\tdelta: {%d,%d}.",delta.h,delta.v);
+ //printf("\tvirtual: {%d,%d}.",virtualMouse.h,virtualMouse.v);
+#endif
+ if(!mainmenu)
+ if(lastMouse.h>gMidPoint.h+100||lastMouse.h<gMidPoint.h-100||lastMouse.v>gMidPoint.v+100||lastMouse.v<gMidPoint.v-100){
+ MyCursorDeviceMoveTo(virtualCursorDevicePtr,gMidPoint.h,gMidPoint.v);
+ lastMouse = gMidPoint;
+ }
+ }
+ }
+}
+
+
+// --------------------------------------------------------------------------
+
+void DoMenu (SInt32 menuResult)
+{
+ SInt16 theMenu;
+ SInt16 theItem;
+ MenuRef theMenuHandle;
+
+ theMenu = HiWord(menuResult);
+ theItem = LoWord(menuResult);
+ theMenuHandle = GetMenuHandle(theMenu);
+
+ switch (theMenu)
+ {
+ case kMenuApple:
+ switch (theItem)
+ {
+ case kAppleAbout:
+ break;
+ default:
+ break;
+ }
+ break;
+ case kMenuFile:
+ switch (theItem)
+ {
+ case kFileQuit:
+ game.quit = true;
+ break;
+ }
+ break;
+ }
+ HiliteMenu(0);
+ DrawMenuBar();
+}
+
+// --------------------------------------------------------------------------
+
+void DoKey (SInt8 theKey, SInt8 theCode)
+{
+ #pragma unused (theCode, theKey)
+ /*if ((theKey == '=') || (theKey == '+'))
+ gfScale *= 1.1;
+ if (theKey == '-')
+ gfScale /= 1.1;*/
+ // do nothing
+}
+
+// --------------------------------------------------------------------------
+
+
+
+/*void DoUpdate (void)
+{
+ static float sps=200;
+ static int count;
+ static float oldmult;
+
+ DoFrameRate();
+
+ count = multiplier*sps;
+ if(count<2)count=2;
+
+ oldmult=multiplier;
+ multiplier/=count;
+
+ for(int i=0;i<count;i++){
+ game.Tick();
+ }
+ multiplier=oldmult;
+
+ game.TickOnce();
+
+ DoMouse();
+
+ DrawGL (&gRectPort);
+}*/
+
+void DoUpdate (void)
+{
+ static float sps=200;
+ static int count;
+ static float oldmult;
+
+ DoFrameRate(1);
+
+ if(multiplier>.6)multiplier=.6;
+
+ game.fps=1/multiplier;
+
+ count = multiplier*sps;
+ if(count<2)count=2;
+ //if(count>10)count=10;
+
+ realmultiplier=multiplier;
+ multiplier*=gamespeed;
+ if(difficulty==1)multiplier*=.9;
+ if(difficulty==0)multiplier*=.8;
+
+ if(game.loading==4)multiplier*=.00001;
+
+ //multiplier*.9;
+ if(slomo&&!mainmenu)multiplier*=slomospeed;
+ //if(freeze)multiplier*=0.00001;
+ oldmult=multiplier;
+ multiplier/=(float)count;
+
+ DoMouse();
+
+ game.TickOnce();
+
+ for(int i=0;i<count;i++){
+ game.Tick();
+ }
+ multiplier=oldmult;
+
+ game.TickOnceAfter();
+
+ DrawGL (&gRectPort);
+}
+
+// --------------------------------------------------------------------------
+
+Boolean WaitNextEventWrapper (EventMask eventMask, EventRecord *theEvent, unsigned long sleep,RgnHandle mouseRgn)
+{
+ return WaitNextEvent (eventMask, theEvent, sleep, mouseRgn);
+}
+
+// --------------------------------------------------------------------------
+
+OSStatus DSpProcessEventWrapper (EventRecord *inEvent, Boolean *outEventWasProcessed)
+{
+ return DSpProcessEvent (inEvent, outEventWasProcessed);
+}
+
+// --------------------------------------------------------------------------
+
+void UpdateWrapper (EventRecord *theEvent)
+{
+ WindowRef whichWindow;
+ GrafPtr pGrafSave;
+
+ whichWindow = (WindowRef) theEvent->message;
+ GetPort (&pGrafSave);
+ SetPort((GrafPtr) GetWindowPort(whichWindow));
+ BeginUpdate(whichWindow);
+ DoUpdate();
+ SetPort((GrafPtr) GetWindowPort(whichWindow));
+ EndUpdate(whichWindow);
+ SetPort (pGrafSave);
+}
+
+// --------------------------------------------------------------------------
+
+pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData)
+{
+ #pragma unused (inTimer, userData)
+ if(!stillloading)DoUpdate ();
+}
+
+// --------------------------------------------------------------------------
+
+EventLoopTimerUPP GetTimerUPP (void)
+{
+ static EventLoopTimerUPP sTimerUPP = NULL;
+
+ if (sTimerUPP == NULL)
+ sTimerUPP = NewEventLoopTimerUPP (IdleTimer);
+
+ return sTimerUPP;
+}
+
+// --------------------------------------------------------------------------
+
+pascal OSStatus mDown (EventHandlerCallRef ref, EventRef e,void * thedata) {
+ EventMouseButton button;
+ OSStatus status;
+
+ status = GetEventParameter (e, kEventParamMouseButton, typeMouseButton, NULL,
+ sizeof (button), NULL, &button);
+
+ buttons[button-1] = true;
+
+ return eventNotHandledErr;
+}
+
+pascal OSStatus mUp (EventHandlerCallRef ref, EventRef e,void * thedata) {
+ EventMouseButton button = 0;
+ OSStatus status;
+
+ status = GetEventParameter (e, kEventParamMouseButton, typeMouseButton, NULL,
+ sizeof (EventMouseButton), NULL, &button);
+
+ buttons[button-1] = false;
+
+ return eventNotHandledErr;
+}
+
+void InstallHandlers(void){
+ OSStatus status;
+ EventTypeSpec spec;
+
+ spec.eventClass = kEventClassMouse;
+ spec.eventKind = kEventMouseDown;
+
+ status = InstallEventHandler (GetApplicationEventTarget(),
+ NewEventHandlerUPP (mDown), 1, &spec, NULL, NULL);
+
+
+ spec.eventKind = kEventMouseUp;
+
+ status = InstallEventHandler (GetApplicationEventTarget(),
+ NewEventHandlerUPP (mUp), 1, &spec, NULL, NULL);
+
+}
+
+void NewEvent(void) {
+ EventRecord e;
+ OSStatus s;
+
+
+ /*ReceiveNextEvent (0, NULL, 1, true, &er);
+
+ s = SendEventToEventTarget (er, GetEventDispatcherTarget());*/
+ WaitNextEvent (everyEvent, &e, 0, NULL);
+
+ DoUpdate();
+}
+
+void DoEvent (void)
+{
+ EventRecord theEvent;
+ WindowRef whichWindow;
+ SInt16 whatPart;
+ Boolean fProcessed;
+
+// profile
+#if __profile__
+ if (noErr == gProfErr)
+ ProfilerSetStatus(TRUE); // turn on profiling
+#endif
+
+ if (WaitNextEventWrapper (everyEvent, &theEvent, gSleepTime, NULL))
+ {
+ DSpProcessEventWrapper (&theEvent, &fProcessed);
+ if (!fProcessed)
+ {
+ switch (theEvent.what)
+ {
+ case mouseDown:
+ whatPart = FindWindow (theEvent.where, &whichWindow);
+ switch (whatPart)
+ {
+ case inContent:
+// if (GetWindowFromPort (gpDSpPort) != FrontWindow())
+// SelectWindow (GetWindowFromPort (gpDSpPort));
+ break;
+ case inMenuBar:
+ {
+ SInt32 menuResult = MenuSelect (theEvent.where);
+ if (HiWord (menuResult) != 0)
+ DoMenu (menuResult);
+ }
+ break;
+ case inDrag:
+ {
+ // full screen no drag
+ }
+ break;
+ case inGrow:
+ {
+ // full screen no grow
+ }
+ break;
+ case inGoAway:
+ {
+ // full screen no go away
+ }
+ break;
+ case inZoomIn:
+ case inZoomOut:
+ {
+ // full screen no zoom
+ }
+ break;
+ case inSysWindow:
+ break;
+ }
+ break;
+ case keyDown:
+ case autoKey:
+ {
+ SInt8 theKey;
+ SInt8 theCode;
+ theKey = theEvent.message & charCodeMask;
+ theCode = (theEvent.message & keyCodeMask) >> 8;
+ if ((theEvent.modifiers & cmdKey) != 0)
+ {
+ SInt32 menuResult = MenuKey (theKey);
+ if (HiWord(menuResult) != 0)
+ DoMenu (menuResult);
+ }
+ else
+ DoKey (theKey, theCode);
+ }
+ break;
+ case updateEvt:
+ {
+ UpdateWrapper (&theEvent);
+ }
+ break;
+ case diskEvt:
+ break;
+ /*case osEvt:
+ if (theEvent.message & 0x01000000) // Suspend/resume event
+ {
+ if (theEvent.message & 0x00000001) // Resume
+ {
+ gSleepTime = kForegroundSleep;
+ gfFrontProcess = true;
+ }
+ else
+ {
+ gSleepTime = kBackgroundSleep; // Suspend
+ gfFrontProcess = false;
+ }
+ }
+ break;*/
+
+ case kHighLevelEvent:
+ AEProcessAppleEvent (&theEvent);
+ break;
+ }
+ }
+ }
+// profile
+#if __profile__
+ if (noErr == gProfErr)
+ ProfilerSetStatus(FALSE); // turn profiling off again
+#endif
+}
+
+// --------------------------------------------------------------------------
+
+void CleanUp (void)
+{
+ MenuHandle hMenu;
+
+// profile
+#if __profile__
+ if (noErr == gProfErr)
+ {
+ ProfilerDump ("\pGL DSp Carbon.prof");
+ ProfilerTerm ();
+ }
+#endif
+
+ game.Dispose();
+
+#if defined kUseFades
+ DSpDebugStr (DSpContext_FadeGammaOut (NULL, NULL)); // fade display, remove for debug
+#endif
+
+ RemoveEventLoopTimer(gTimer);
+ gTimer = NULL;
+
+ DeleteFontGL (gFontList);
+ CleanupAGL (gaglContext); // Cleanup the OpenGL context
+ gaglContext = 0;
+ if (gpDSpPort)
+ {
+ ShutdownDSp (gpDSpPort); // DSp shutdown
+ gpDSpPort = NULL;
+ }
+
+
+ hMenu = GetMenuHandle (kMenuFile);
+ DeleteMenu (kMenuFile);
+ DisposeMenu (hMenu);
+
+ hMenu = GetMenuHandle (kMenuApple);
+ DeleteMenu (kMenuApple);
+ DisposeMenu (hMenu);
+
+#if defined kUseFades
+ DSpDebugStr (DSpContext_FadeGammaIn (NULL, NULL)); // fade display, remove for debug
+#endif
+ DSpShutdown ();
+
+ ShowCursor();
+}
+
+// --------------------------------------------------------------------------
+#include <iostream>
+#include <InternetConfig.h>
+
+/*void openURL()
+{
+#ifdef Q_WS_MAC
+ QString url("http://www.wolfire.com/");
+ ICInstance icInstance
+ OSType psiSignature = 'Psi ';
+ OSStatus error = ::ICStart( &icInstance, psiSignature);
+ if(error=noErr){
+ ConstStr255Param hint( 0x0 );
+ const char* data = url.latin1();
+ long length = url.length();
+ long start( 0 );
+ long end( length );
+ ::ICLaunchURL( icInstance, hint, data, length, &start, &end);
+ ICStop( icInstance);
+ }
+ #endif
+}*/
+
+void LaunchURL(char *url)
+{
+ ICInstance gICInstance;
+ ICStart (&gICInstance, 0);
+ long int start,fin;
+ start=0;
+ fin=strlen(url);
+ ICLaunchURL(gICInstance, "\p" ,url, fin, &start, &fin);
+}
+
+
+
+int main (void)
+{
+ try {
+ if (SetUp ()) {
+ InstallHandlers();
+ while (!gDone&&!game.quit&&(!game.tryquit||!game.registered)) {
+ NewEvent ();
+ }
+ }
+ CleanUp ();
+ if(game.registernow){
+ char url[100];
+ sprintf(url,"http://www.wolfire.com/register.html");
+ LaunchURL(url);
+ }
+ return 0;
+ } catch (const std::exception& error) {
+ ofstream opstream("error.txt");
+ opstream << "Caught exception: " << error.what() << std::endl;
+ opstream.close();
+ }
+}
\ No newline at end of file
--- /dev/null
+#include <vld.h>
+#include "Game.h"
+
+// ADDED GWC
+#pragma comment(lib, "opengl32.lib")
+#pragma comment(lib, "glu32.lib")
+#pragma comment(lib, "glaux.lib")
+
+extern bool buttons[3];
+extern float multiplier;
+extern float screenwidth,screenheight;
+extern float sps;
+extern float realmultiplier;
+extern int slomo;
+extern bool ismotionblur;
+extern float usermousesensitivity;
+extern int detail;
+extern bool floatjump;
+extern bool cellophane;
+// MODIFIED GWC
+//extern int terraindetail;
+//extern int texdetail;
+extern float terraindetail;
+extern float texdetail;
+extern int bloodtoggle;
+extern bool osx;
+extern bool autoslomo;
+extern bool foliage;
+extern bool musictoggle;
+extern bool trilinear;
+extern float gamespeed;
+extern int difficulty;
+extern bool damageeffects;
+extern int numplayers;
+extern bool decals;
+extern bool invertmouse;
+extern bool texttoggle;
+extern bool ambientsound;
+extern bool mousejump;
+extern bool freeze;
+extern Person player[maxplayers];
+extern bool vblsync;
+extern bool stillloading;
+extern bool showpoints;
+extern bool alwaysblur;
+extern bool immediate;
+extern bool velocityblur;
+extern bool debugmode;
+extern int mainmenu;
+/*extern*/ bool gameFocused;
+extern int kBitsPerPixel;
+extern float slomospeed;
+extern float slomofreq;
+extern float oldgamespeed;
+extern float volume;
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <fstream>
+#include <iostream>
+#include "gl.h"
+#include "WinDefs.h"
+#include <shellapi.h>
+#include "fmod.h"
+
+#include "res/resource.h"
+
+using namespace std;
+
+
+unsigned int resolutionDepths[8][2] = {0};
+
+bool selectDetail(int & width, int & height, int & bpp, int & detail);
+int closestResolution(int width, int height);
+int resolutionID(int width, int height);
+
+void ReportError (char * strError);
+
+void SetupDSpFullScreen();
+void ShutdownDSp();
+
+void DrawGL(Game & game);
+
+void CreateGLWindow (void);
+Boolean SetUp (Game & game);
+void DoKey (SInt8 theKey, SInt8 theCode);
+void DoUpdate (Game & game);
+
+void DoEvent (void);
+void CleanUp (void);
+
+
+// statics/globals (internal only) ------------------------------------------
+
+Point delta;
+
+static const char g_wndClassName[]={ "LUGARUWINDOWCLASS" };
+
+static HINSTANCE g_appInstance;
+static HWND g_windowHandle;
+static HGLRC hRC;
+static bool g_button, fullscreen = true;
+
+
+// Menu defs
+enum
+{
+ kFileQuit = 1
+};
+
+enum
+{
+ kForegroundSleep = 10,
+ kBackgroundSleep = 10000
+};
+
+
+int kContextWidth;
+int kContextHeight;
+
+const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
+
+extern HDC hDC;
+GLuint gFontList;
+char gcstrMode [256] = "";
+
+UInt32 gSleepTime = kForegroundSleep;
+Boolean gDone = false, gfFrontProcess = true;
+
+Game * pgame = 0;
+
+// --------------------------------------------------------------------------
+
+void ReportError (char * strError)
+{
+ throw std::exception( strError);
+
+ /* char errMsgCStr [256];
+ Str255 strErr;
+
+ sprintf (errMsgCStr, "%s", strError);
+
+ // out as debug string
+ CToPStr (strErr, errMsgCStr);
+ DebugStr (strErr);
+ */
+}
+
+void SetupDSpFullScreen ()
+{
+ LOGFUNC;
+
+ if (fullscreen)
+ {
+ DEVMODE dmScreenSettings;
+ memset( &dmScreenSettings, 0, sizeof( dmScreenSettings));
+ dmScreenSettings.dmSize = sizeof( dmScreenSettings);
+ dmScreenSettings.dmPelsWidth = kContextWidth;
+ dmScreenSettings.dmPelsHeight = kContextHeight;
+ dmScreenSettings.dmBitsPerPel = kBitsPerPixel;
+ dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+ // set video mode
+ if (ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+ {
+ ReportError( "Could not set display mode");
+ return;
+ }
+ }
+
+ ShowCursor(FALSE);
+}
+
+
+void ShutdownDSp ()
+{
+ LOGFUNC;
+
+ if (fullscreen)
+ {
+ ChangeDisplaySettings( NULL, 0);
+ }
+
+ ShowCursor(TRUE);
+}
+
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+// OpenGL Drawing
+
+void DrawGL (Game & game)
+{
+ if (hDC == 0)
+ return;
+
+ game.DrawGLScene();
+}
+
+
+
+// --------------------------------------------------------------------------
+
+static Point gMidPoint;
+
+Boolean SetUp (Game & game)
+{
+ char string[10];
+
+ LOGFUNC;
+
+ randSeed = UpTime().lo;
+
+ osx = 0;
+// ifstream ipstream(":Data:config.txt", std::ios::in /*| std::ios::nocreate*/);
+ ifstream ipstream("./Data/config.txt", std::ios::in /*| std::ios::nocreate*/);
+ detail=1;
+ ismotionblur=0;
+ usermousesensitivity=1;
+ kContextWidth=640;
+ kContextHeight=480;
+ kBitsPerPixel = 32;
+ floatjump=0;
+ cellophane=0;
+ texdetail=4;
+ autoslomo=1;
+ decals=1;
+ invertmouse=0;
+ bloodtoggle=0;
+ terraindetail=2;
+ foliage=1;
+ musictoggle=1;
+ trilinear=1;
+ gamespeed=1;
+ difficulty=1;
+ damageeffects=0;
+ texttoggle=1;
+ alwaysblur=0;
+ showpoints=0;
+ immediate=0;
+ velocityblur=0;
+
+ slomospeed=0.25;
+ slomofreq=8012;
+
+ volume = 0.8f;
+
+ game.crouchkey=MAC_SHIFT_KEY;
+ game.jumpkey=MAC_SPACE_KEY;
+ game.leftkey=MAC_A_KEY;
+ game.forwardkey=MAC_W_KEY;
+ game.backkey=MAC_S_KEY;
+ game.rightkey=MAC_D_KEY;
+ game.drawkey=MAC_E_KEY;
+ game.throwkey=MAC_Q_KEY;
+ game.attackkey=MAC_MOUSEBUTTON1;
+ game.chatkey=MAC_T_KEY;
+ numplayers=1;
+ ambientsound=1;
+ vblsync=0;
+ debugmode=0;
+
+ selectDetail(kContextWidth, kContextHeight, kBitsPerPixel, detail);
+
+ if(!ipstream) {
+ //ofstream opstream(":Data:config.txt");
+ ofstream opstream("./Data/config.txt");
+ opstream << "Screenwidth:\n";
+ opstream << kContextWidth;
+ opstream << "\nScreenheight:\n";
+ opstream << kContextHeight;
+ opstream << "\nMouse sensitivity:\n";
+ opstream << usermousesensitivity;
+ opstream << "\nBlur(0,1):\n";
+ opstream << ismotionblur;
+ opstream << "\nOverall Detail(0,1,2) higher=better:\n";
+ opstream << detail;
+ opstream << "\nFloating jump:\n";
+ opstream << floatjump;
+ opstream << "\nMouse jump:\n";
+ opstream << mousejump;
+ opstream << "\nAmbient sound:\n";
+ opstream << ambientsound;
+ opstream << "\nBlood (0,1,2):\n";
+ opstream << bloodtoggle;
+ opstream << "\nAuto slomo:\n";
+ opstream << autoslomo;
+ opstream << "\nFoliage:\n";
+ opstream << foliage;
+ opstream << "\nMusic:\n";
+ opstream << musictoggle;
+ opstream << "\nTrilinear:\n";
+ opstream << trilinear;
+ opstream << "\nDecals(shadows,blood puddles,etc):\n";
+ opstream << decals;
+ opstream << "\nInvert mouse:\n";
+ opstream << invertmouse;
+ opstream << "\nGamespeed:\n";
+ opstream << gamespeed;
+ opstream << "\nDifficulty(0,1,2) higher=harder:\n";
+ opstream << difficulty;
+ opstream << "\nDamage effects(blackout, doublevision):\n";
+ opstream << damageeffects;
+ opstream << "\nText:\n";
+ opstream << texttoggle;
+ opstream << "\nDebug:\n";
+ opstream << debugmode;
+ opstream << "\nVBL Sync:\n";
+ opstream << vblsync;
+ opstream << "\nShow Points:\n";
+ opstream << showpoints;
+ opstream << "\nAlways Blur:\n";
+ opstream << alwaysblur;
+ opstream << "\nImmediate mode (turn on on G5):\n";
+ opstream << immediate;
+ opstream << "\nVelocity blur:\n";
+ opstream << velocityblur;
+ opstream << "\nVolume:\n";
+ opstream << volume;
+ opstream << "\nForward key:\n";
+ opstream << KeyToChar(game.forwardkey);
+ opstream << "\nBack key:\n";
+ opstream << KeyToChar(game.backkey);
+ opstream << "\nLeft key:\n";
+ opstream << KeyToChar(game.leftkey);
+ opstream << "\nRight key:\n";
+ opstream << KeyToChar(game.rightkey);
+ opstream << "\nJump key:\n";
+ opstream << KeyToChar(game.jumpkey);
+ opstream << "\nCrouch key:\n";
+ opstream << KeyToChar(game.crouchkey);
+ opstream << "\nDraw key:\n";
+ opstream << KeyToChar(game.drawkey);
+ opstream << "\nThrow key:\n";
+ opstream << KeyToChar(game.throwkey);
+ opstream << "\nAttack key:\n";
+ opstream << KeyToChar(game.attackkey);
+ opstream << "\nChat key:\n";
+ opstream << KeyToChar(game.chatkey);
+ opstream.close();
+ }
+ if(ipstream){
+ int i;
+ ipstream.ignore(256,'\n');
+ ipstream >> kContextWidth;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> kContextHeight;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> usermousesensitivity;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ ismotionblur = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> detail;
+ if(detail!=0)kBitsPerPixel=32;
+ else kBitsPerPixel=16;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ floatjump = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ mousejump = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ ambientsound = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> bloodtoggle;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ autoslomo = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ foliage = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ musictoggle = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ trilinear = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ decals = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ invertmouse = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> gamespeed;
+ oldgamespeed=gamespeed;
+ if(oldgamespeed==0){
+ gamespeed=1;
+ oldgamespeed=1;
+ }
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> difficulty;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ damageeffects = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ texttoggle = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ debugmode = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ vblsync = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ showpoints = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ alwaysblur = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ immediate = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> i;
+ velocityblur = (i != 0);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> volume;
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.forwardkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.backkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.leftkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.rightkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.jumpkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.crouchkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.drawkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.throwkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.attackkey=CharToKey(string);
+ ipstream.ignore(256,'\n');
+ ipstream.ignore(256,'\n');
+ ipstream >> string;
+ game.chatkey=CharToKey(string);
+ ipstream.close();
+
+ if(detail>2)detail=2;
+ if(detail<0)detail=0;
+ if(screenwidth>3000)screenwidth=640;
+ if(screenwidth<0)screenwidth=640;
+ if(screenheight>3000)screenheight=480;
+ if(screenheight<0)screenheight=480;
+ }
+ if(kBitsPerPixel!=32&&kBitsPerPixel!=16){
+ kBitsPerPixel=16;
+ }
+
+
+ selectDetail(kContextWidth, kContextHeight, kBitsPerPixel, detail);
+
+ SetupDSpFullScreen();
+
+ //------------------------------------------------------------------
+ // create window
+ int x = 0, y = 0;
+ RECT r = {0, 0, kContextWidth-1, kContextHeight-1};
+ DWORD dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE;
+ DWORD dwExStyle = WS_EX_APPWINDOW;
+
+ if (fullscreen)
+ {
+ dwStyle |= WS_POPUP;
+ }
+ else
+ {
+
+ dwStyle |= WS_OVERLAPPEDWINDOW;
+ dwExStyle |= WS_EX_WINDOWEDGE;
+ }
+
+ AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
+
+ if (!fullscreen)
+ {
+ x = (GetSystemMetrics(SM_CXSCREEN) >> 1) - ((r.right - r.left + 1) >> 1);
+ y = (GetSystemMetrics(SM_CYSCREEN) >> 1) - ((r.bottom - r.top + 1) >> 1);
+ }
+
+ g_windowHandle=CreateWindowEx(
+ dwExStyle,
+ g_wndClassName, "Lugaru", dwStyle,
+ x, y,
+// kContextWidth, kContextHeight,
+ r.right - r.left + 1, r.bottom - r.top + 1,
+ NULL,NULL,g_appInstance,NULL );
+ if (!g_windowHandle)
+ {
+ ReportError("Could not create window");
+ return false;
+ }
+
+
+ //------------------------------------------------------------------
+ // setup OpenGL
+
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
+ 1, // Version Number
+ PFD_DRAW_TO_WINDOW | // Format Must Support Window
+ PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
+ PFD_DOUBLEBUFFER, // Must Support Double Buffering
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ kBitsPerPixel, // Select Our Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored
+ 16, // 16Bit Z-Buffer (Depth Buffer)
+ 0, // No Stencil Buffer
+ 0, // No Auxiliary Buffer
+ PFD_MAIN_PLANE, // Main Drawing Layer
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+
+ if (!(hDC = GetDC( g_windowHandle)))
+ ReportError( "Could not get device context");
+
+ GLuint PixelFormat;
+ if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
+ {
+ ReportError( "Could not find appropriate pixel format");
+ return false;
+ }
+
+ if (!DescribePixelFormat(hDC, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
+ {
+ ReportError( "Could not retrieve pixel format");
+ return false;
+ }
+
+ if (!SetPixelFormat( hDC, PixelFormat, &pfd))
+ {
+ ReportError( "Could not set pixel format");
+ return false;
+ }
+
+ if (!(hRC = wglCreateContext(hDC)))
+ {
+ ReportError( "Could not create rendering context");
+ return false;
+ }
+
+ if (!wglMakeCurrent(hDC, hRC))
+ {
+ ReportError( "Could not activate rendering context");
+ return false;
+ }
+
+ if (fullscreen)
+ {
+ // Place the window above all topmost windows
+ SetWindowPos( g_windowHandle, HWND_TOPMOST, 0,0,0,0,
+ SWP_NOMOVE | SWP_NOSIZE );
+ }
+
+ SetForegroundWindow(g_windowHandle);
+ SetFocus(g_windowHandle);
+
+ glClear( GL_COLOR_BUFFER_BIT );
+ SwapBuffers( hDC );
+
+ // clear all states
+ glDisable( GL_ALPHA_TEST);
+ glDisable( GL_BLEND);
+ glDisable( GL_DEPTH_TEST);
+ // glDisable( GL_DITHER);
+ glDisable( GL_FOG);
+ glDisable( GL_LIGHTING);
+ glDisable( GL_LOGIC_OP);
+ glDisable( GL_STENCIL_TEST);
+ glDisable( GL_TEXTURE_1D);
+ glDisable( GL_TEXTURE_2D);
+ glPixelTransferi( GL_MAP_COLOR, GL_FALSE);
+ glPixelTransferi( GL_RED_SCALE, 1);
+ glPixelTransferi( GL_RED_BIAS, 0);
+ glPixelTransferi( GL_GREEN_SCALE, 1);
+ glPixelTransferi( GL_GREEN_BIAS, 0);
+ glPixelTransferi( GL_BLUE_SCALE, 1);
+ glPixelTransferi( GL_BLUE_BIAS, 0);
+ glPixelTransferi( GL_ALPHA_SCALE, 1);
+ glPixelTransferi( GL_ALPHA_BIAS, 0);
+
+ // set initial rendering states
+ glShadeModel( GL_SMOOTH);
+ glClearDepth( 1.0f);
+ glDepthFunc( GL_LEQUAL);
+ glDepthMask( GL_TRUE);
+ // glDepthRange( FRONT_CLIP, BACK_CLIP);
+ glEnable( GL_DEPTH_TEST);
+ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glCullFace( GL_FRONT);
+ glEnable( GL_CULL_FACE);
+ glEnable( GL_LIGHTING);
+// glEnable( GL_LIGHT_MODEL_AMBIENT);
+ glEnable( GL_DITHER);
+ glEnable( GL_COLOR_MATERIAL);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glAlphaFunc( GL_GREATER, 0.5f);
+
+ if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION ||
+ iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION ||
+ ilutGetInteger(ILUT_VERSION_NUM) < ILUT_VERSION)
+ {
+ ReportError("DevIL version is different...exiting!\n");
+ return false;
+ }
+
+ ilInit();
+ iluInit();
+ ilutInit();
+
+ ilutRenderer(ILUT_OPENGL);
+
+ ilEnable(IL_ORIGIN_SET);
+ ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
+
+ GLint width = kContextWidth;
+ GLint height = kContextHeight;
+ gMidPoint.h = width / 2;
+ gMidPoint.v = height / 2;
+ screenwidth=width;
+ screenheight=height;
+
+ game.newdetail=detail;
+ game.newscreenwidth=screenwidth;
+ game.newscreenheight=screenheight;
+
+ game.InitGame();
+
+ return true;
+}
+
+
+static void DoMouse(Game & game)
+{
+ static Point lastMouse = {-1,-1};
+ Point globalMouse;
+
+ POINT pos;
+ GetCursorPos(&pos);
+ ScreenToClient(g_windowHandle, &pos);
+ globalMouse.h = pos.x;
+ globalMouse.v = pos.y;
+
+ if (lastMouse.h == globalMouse.h && lastMouse.v == globalMouse.v)
+ {
+ game.deltah=0;
+ game.deltav=0;
+ }
+ else
+ {
+ static Point virtualMouse = {0,0};
+ delta = globalMouse;
+
+ delta.h -= lastMouse.h;
+ delta.v -= lastMouse.v;
+ lastMouse.h = pos.x;
+ lastMouse.v = pos.y;
+
+ if(mainmenu||(abs(delta.h)<10*realmultiplier*1000&&abs(delta.v)<10*realmultiplier*1000)){
+ game.deltah=delta.h*usermousesensitivity;
+ game.deltav=delta.v*usermousesensitivity;
+ game.mousecoordh=globalMouse.h;
+ game.mousecoordv=globalMouse.v;
+ }
+
+ if(!mainmenu)
+ {
+ if(lastMouse.h>gMidPoint.h+100||lastMouse.h<gMidPoint.h-100||lastMouse.v>gMidPoint.v+100||lastMouse.v<gMidPoint.v-100){
+ pos.x = gMidPoint.h;
+ pos.y = gMidPoint.v;
+ ClientToScreen(g_windowHandle, &pos);
+ //SetCursorPos( gMidPoint.h,gMidPoint.v);
+ SetCursorPos(pos.x, pos.y);
+ lastMouse = gMidPoint;
+ }
+ }
+ }
+}
+
+
+
+// --------------------------------------------------------------------------
+
+void DoKey (SInt8 theKey, SInt8 theCode)
+{
+ // do nothing
+}
+
+// --------------------------------------------------------------------------
+
+
+
+void DoFrameRate (int update)
+{
+ static long frames = 0;
+
+ static AbsoluteTime time = {0,0};
+ static AbsoluteTime frametime = {0,0};
+ AbsoluteTime currTime = UpTime ();
+ double deltaTime = (float) AbsoluteDeltaToDuration (currTime, frametime);
+
+ if (0 > deltaTime) // if negative microseconds
+ deltaTime /= -1000000.0;
+ else // else milliseconds
+ deltaTime /= 1000.0;
+
+ multiplier=deltaTime;
+ if(multiplier<.001)multiplier=.001;
+ if(multiplier>10)multiplier=10;
+ if(update)frametime = currTime; // reset for next time interval
+
+ deltaTime = (float) AbsoluteDeltaToDuration (currTime, time);
+
+ if (0 > deltaTime) // if negative microseconds
+ deltaTime /= -1000000.0;
+ else // else milliseconds
+ deltaTime /= 1000.0;
+ frames++;
+ if (0.001 <= deltaTime) // has update interval passed
+ {
+ if(update){
+ time = currTime; // reset for next time interval
+ frames = 0;
+ }
+ }
+}
+
+
+void DoUpdate (Game & game)
+{
+ static float sps=200;
+ static int count;
+ static float oldmult;
+
+ DoFrameRate(1);
+ if(multiplier>.6)multiplier=.6;
+
+ game.fps=1/multiplier;
+
+ count = multiplier*sps;
+ if(count<2)count=2;
+ //if(count>10)count=10;
+
+ realmultiplier=multiplier;
+ multiplier*=gamespeed;
+ if(difficulty==1)multiplier*=.9;
+ if(difficulty==0)multiplier*=.8;
+
+ if(game.loading==4)multiplier*=.00001;
+ //multiplier*.9;
+ if(slomo&&!mainmenu)multiplier*=slomospeed;
+ //if(freeze)multiplier*=0.00001;
+ oldmult=multiplier;
+ multiplier/=(float)count;
+
+ DoMouse(game);
+
+ game.TickOnce();
+
+ for(int i=0;i<count;i++)
+ {
+ game.Tick();
+ }
+ multiplier=oldmult;
+
+ game.TickOnceAfter();
+/* - Debug code to test how many channels were active on average per frame
+ static long frames = 0;
+
+ static AbsoluteTime start = {0,0};
+ AbsoluteTime currTime = UpTime ();
+ static int num_channels = 0;
+
+ num_channels += FSOUND_GetChannelsPlaying();
+ double deltaTime = (float) AbsoluteDeltaToDuration (currTime, start);
+
+ if (0 > deltaTime) // if negative microseconds
+ deltaTime /= -1000000.0;
+ else // else milliseconds
+ deltaTime /= 1000.0;
+
+ ++frames;
+
+ if (deltaTime >= 1)
+ {
+ start = currTime;
+ float avg_channels = (float)num_channels / (float)frames;
+
+ ofstream opstream("log.txt",ios::app);
+ opstream << "Average frame count: ";
+ opstream << frames;
+ opstream << " frames - ";
+ opstream << avg_channels;
+ opstream << " per frame.\n";
+ opstream.close();
+
+ frames = 0;
+ num_channels = 0;
+ }
+*/
+ DrawGL (game);
+}
+
+// --------------------------------------------------------------------------
+
+
+void CleanUp (void)
+{
+ LOGFUNC;
+
+// game.Dispose();
+
+ ilShutDown();
+
+ if (hRC)
+ {
+ wglMakeCurrent( NULL, NULL);
+ wglDeleteContext( hRC);
+ hRC = NULL;
+ }
+
+ if (hDC)
+ {
+ ReleaseDC( g_windowHandle, hDC);
+ hDC = NULL;
+ }
+
+ if (g_windowHandle)
+ {
+ ShowWindow( g_windowHandle, SW_HIDE );
+ DestroyWindow( g_windowHandle);
+ g_windowHandle = NULL;
+ }
+
+ ShutdownDSp ();
+ ClipCursor(NULL);
+}
+
+// --------------------------------------------------------------------------
+
+static bool g_focused = true;
+
+
+static bool IsFocused()
+{
+ if (!g_focused)
+ return false;
+
+ if (GetActiveWindow() != g_windowHandle)
+ return false;
+
+ if (IsIconic( g_windowHandle))
+ return false;
+
+ return true;
+}
+
+
+int main (void)
+{
+ LOGFUNC;
+
+ try
+ {
+ bool regnow = false;
+ {
+ Game game;
+ pgame = &game;
+
+ //ofstream os("error.txt");
+ //os.close();
+ //ofstream os("log.txt");
+ //os.close();
+
+ SetUp (game);
+
+ while (!gDone&&!game.quit&&(!game.tryquit||!game.registered))
+ {
+ if (IsFocused())
+ {
+ gameFocused = true;
+
+ // check windows messages
+ MSG msg;
+ // message pump
+ while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD ) )
+ {
+ if( msg.message == WM_QUIT )
+ {
+ gDone=true;
+ break;
+ }
+ else
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+
+ // game
+ DoUpdate(game);
+ }
+ else
+ {
+ if (gameFocused)
+ {
+ // allow game chance to pause
+ gameFocused = false;
+ DoUpdate(game);
+ }
+
+ // game is not in focus, give CPU time to other apps by waiting for messages instead of 'peeking'
+ MSG msg;
+ BOOL bRet;
+ //if (GetMessage( &msg, g_windowHandle, 0, 0 ))
+ /*if (GetMessage( &msg, NULL, 0, 0 ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }*/
+ if ( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
+ {
+ if (bRet <= 0)
+ {
+ // handle the error and possibly exit
+ gDone=true;
+ }
+ else
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ }
+
+ regnow = game.registernow;
+ }
+ pgame = 0;
+
+ CleanUp ();
+// if(game.registernow){
+ if(regnow)
+ {
+ char url[100];
+ sprintf(url,"http://www.wolfire.com/registerpc.html");
+ // LaunchURL(url);
+ ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
+ }
+ return 0;
+ }
+ catch (const std::exception& error)
+ {
+ CleanUp();
+
+ std::string e = "Caught exception: ";
+ e += error.what();
+
+ LOG(e, Logger::LOG_ERR);
+
+ MessageBox(g_windowHandle, error.what(), "ERROR", MB_OK | MB_ICONEXCLAMATION);
+ }
+
+ CleanUp();
+
+ return -1;
+}
+
+
+
+ // --------------------------------------------------------------------------
+
+
+#define MAX_WINKEYS 256
+ static unsigned short KeyTable[MAX_WINKEYS]=
+ {
+ 0xffff, // (0)
+ MAC_MOUSEBUTTON1, // VK_LBUTTON (1)
+ MAC_MOUSEBUTTON2, // VK_RBUTTON (2)
+ 0xffff, // VK_CANCEL (3)
+ 0xffff, // VK_MBUTTON (4)
+ 0xffff, // (5)
+ 0xffff, // (6)
+ 0xffff, // (7)
+ MAC_DELETE_KEY, // VK_BACK (8)
+ MAC_TAB_KEY, // VK_TAB (9)
+ 0xffff, // (10)
+ 0xffff, // (11)
+ 0xffff, // VK_CLEAR (12)
+ MAC_RETURN_KEY, // VK_RETURN (13)
+ 0xffff, // (14)
+ 0xffff, // (15)
+ MAC_SHIFT_KEY, // VK_SHIFT (16)
+ MAC_CONTROL_KEY, // VK_CONTROL (17)
+ MAC_OPTION_KEY, // VK_MENU (18)
+ 0xffff, // VK_PAUSE (19)
+ MAC_CAPS_LOCK_KEY, // #define VK_CAPITAL (20)
+ 0xffff, // (21)
+ 0xffff, // (22)
+ 0xffff, // (23)
+ 0xffff, // (24)
+ 0xffff, // (25)
+ 0xffff, // (26)
+ MAC_ESCAPE_KEY, // VK_ESCAPE (27)
+ 0xffff, // (28)
+ 0xffff, // (29)
+ 0xffff, // (30)
+ 0xffff, // (31)
+ MAC_SPACE_KEY, // VK_SPACE (32)
+ MAC_PAGE_UP_KEY, // VK_PRIOR (33)
+ MAC_PAGE_DOWN_KEY, // VK_NEXT (34)
+ MAC_END_KEY, // VK_END (35)
+ MAC_HOME_KEY, // VK_HOME (36)
+ MAC_ARROW_LEFT_KEY, // VK_LEFT (37)
+ MAC_ARROW_UP_KEY, // VK_UP (38)
+ MAC_ARROW_RIGHT_KEY, // VK_RIGHT (39)
+ MAC_ARROW_DOWN_KEY, // VK_DOWN (40)
+ 0xffff, // VK_SELECT (41)
+ 0xffff, // VK_PRINT (42)
+ 0xffff, // VK_EXECUTE (43)
+ 0xffff, // VK_SNAPSHOT (44)
+ MAC_INSERT_KEY, // VK_INSERT (45)
+ MAC_DEL_KEY, // VK_DELETE (46)
+ 0xffff, // VK_HELP (47)
+ MAC_0_KEY, // VK_0 (48)
+ MAC_1_KEY, // VK_1 (49)
+ MAC_2_KEY, // VK_2 (50)
+ MAC_3_KEY, // VK_3 (51)
+ MAC_4_KEY, // VK_4 (52)
+ MAC_5_KEY, // VK_5 (53)
+ MAC_6_KEY, // VK_6 (54)
+ MAC_7_KEY, // VK_7 (55)
+ MAC_8_KEY, // VK_8 (56)
+ MAC_9_KEY, // VK_9 (57)
+ 0xffff, // (58)
+ 0xffff, // (59)
+ 0xffff, // (60)
+ 0xffff, // (61)
+ 0xffff, // (62)
+ 0xffff, // (63)
+ 0xffff, // (64)
+ MAC_A_KEY, // VK_A (65)
+ MAC_B_KEY, // VK_B (66)
+ MAC_C_KEY, // VK_C (67)
+ MAC_D_KEY, // VK_D (68)
+ MAC_E_KEY, // VK_E (69)
+ MAC_F_KEY, // VK_F (70)
+ MAC_G_KEY, // VK_G (71)
+ MAC_H_KEY, // VK_H (72)
+ MAC_I_KEY, // VK_I (73)
+ MAC_J_KEY, // VK_J (74)
+ MAC_K_KEY, // VK_K (75)
+ MAC_L_KEY, // VK_L (76)
+ MAC_M_KEY, // VK_M (77)
+ MAC_N_KEY, // VK_N (78)
+ MAC_O_KEY, // VK_O (79)
+ MAC_P_KEY, // VK_P (80)
+ MAC_Q_KEY, // VK_Q (81)
+ MAC_R_KEY, // VK_R (82)
+ MAC_S_KEY, // VK_S (83)
+ MAC_T_KEY, // VK_T (84)
+ MAC_U_KEY, // VK_U (85)
+ MAC_V_KEY, // VK_V (86)
+ MAC_W_KEY, // VK_W (87)
+ MAC_X_KEY, // VK_X (88)
+ MAC_Y_KEY, // VK_Y (89)
+ MAC_Z_KEY, // VK_Z (90)
+ 0xffff, // (91)
+ 0xffff, // (92)
+ 0xffff, // (93)
+ 0xffff, // (94)
+ 0xffff, // (95)
+ MAC_NUMPAD_0_KEY, // VK_NUMPAD0 (96)
+ MAC_NUMPAD_1_KEY, // VK_NUMPAD1 (97)
+ MAC_NUMPAD_2_KEY, // VK_NUMPAD2 (98)
+ MAC_NUMPAD_3_KEY, // VK_NUMPAD3 (99)
+ MAC_NUMPAD_4_KEY, // VK_NUMPAD4 (100)
+ MAC_NUMPAD_5_KEY, // VK_NUMPAD5 (101)
+ MAC_NUMPAD_6_KEY, // VK_NUMPAD6 (102)
+ MAC_NUMPAD_7_KEY, // VK_NUMPAD7 (103)
+ MAC_NUMPAD_8_KEY, // VK_NUMPAD8 (104)
+ MAC_NUMPAD_9_KEY, // VK_NUMPAD9 (105)
+ MAC_NUMPAD_ASTERISK_KEY, // VK_MULTIPLY (106)
+ MAC_NUMPAD_PLUS_KEY, // VK_ADD (107)
+ MAC_NUMPAD_ENTER_KEY, // VK_SEPARATOR (108)
+ MAC_NUMPAD_MINUS_KEY, // VK_SUBTRACT (109)
+ MAC_NUMPAD_PERIOD_KEY, // VK_DECIMAL (110)
+ MAC_NUMPAD_SLASH_KEY, // VK_DIVIDE (111)
+ MAC_F1_KEY, // VK_F1 (112)
+ MAC_F2_KEY, // VK_F2 (113)
+ MAC_F3_KEY, // VK_F3 (114)
+ MAC_F4_KEY, // VK_F4 (115)
+ MAC_F5_KEY, // VK_F5 (116)
+ MAC_F6_KEY, // VK_F6 (117)
+ MAC_F7_KEY, // VK_F7 (118)
+ MAC_F8_KEY, // VK_F8 (119)
+ MAC_F9_KEY, // VK_F9 (120)
+ MAC_F10_KEY, // VK_F10 (121)
+ MAC_F11_KEY, // VK_F11 (122)
+ MAC_F12_KEY, // VK_F12 (123)
+ 0xffff, // (124)
+ 0xffff, // (125)
+ 0xffff, // (126)
+ 0xffff, // (127)
+ 0xffff, // (128)
+ 0xffff, // (129)
+ 0xffff, // (130)
+ 0xffff, // (131)
+ 0xffff, // (132)
+ 0xffff, // (133)
+ 0xffff, // (134)
+ 0xffff, // (135)
+ 0xffff, // (136)
+ 0xffff, // (137)
+ 0xffff, // (138)
+ 0xffff, // (139)
+ 0xffff, // (130)
+ 0xffff, // (141)
+ 0xffff, // (142)
+ 0xffff, // (143)
+ 0xffff, // VK_NUMLOCK (144)
+ 0xffff, // VK_SCROLL (145)
+ 0xffff, // (146)
+ 0xffff, // (147)
+ 0xffff, // (148)
+ 0xffff, // (149)
+ 0xffff, // (150)
+ 0xffff, // (151)
+ 0xffff, // (152)
+ 0xffff, // (153)
+ 0xffff, // (154)
+ 0xffff, // (155)
+ 0xffff, // (156)
+ 0xffff, // (157)
+ 0xffff, // (158)
+ 0xffff, // (159)
+ MAC_SHIFT_KEY, // VK_LSHIFT (160)
+ MAC_SHIFT_KEY, // VK_RSHIFT (161)
+ MAC_CONTROL_KEY, // VK_LCONTROL (162)
+ MAC_CONTROL_KEY, // VK_RCONTROL (163)
+ MAC_OPTION_KEY, // VK_LMENU (164)
+ MAC_OPTION_KEY, // VK_RMENU (165)
+ 0xffff, // (166)
+ 0xffff, // (167)
+ 0xffff, // (168)
+ 0xffff, // (169)
+ 0xffff, // (170)
+ 0xffff, // (171)
+ 0xffff, // (172)
+ 0xffff, // (173)
+ 0xffff, // (174)
+ 0xffff, // (175)
+ 0xffff, // (176)
+ 0xffff, // (177)
+ 0xffff, // (178)
+ 0xffff, // (179)
+ 0xffff, // (180)
+ 0xffff, // (181)
+ 0xffff, // (182)
+ 0xffff, // (183)
+ 0xffff, // (184)
+ 0xffff, // (185)
+ MAC_SEMICOLON_KEY, // (186)
+ MAC_PLUS_KEY, // (187)
+ MAC_COMMA_KEY, // (188)
+ MAC_MINUS_KEY, // (189)
+ MAC_PERIOD_KEY, // (190)
+ MAC_SLASH_KEY, // (191)
+ MAC_TILDE_KEY, // (192)
+ 0xffff, // (193)
+ 0xffff, // (194)
+ 0xffff, // (195)
+ 0xffff, // (196)
+ 0xffff, // (197)
+ 0xffff, // (198)
+ 0xffff, // (199)
+ 0xffff, // (200)
+ 0xffff, // (201)
+ 0xffff, // (202)
+ 0xffff, // (203)
+ 0xffff, // (204)
+ 0xffff, // (205)
+ 0xffff, // (206)
+ 0xffff, // (207)
+ 0xffff, // (208)
+ 0xffff, // (209)
+ 0xffff, // (210)
+ 0xffff, // (211)
+ 0xffff, // (212)
+ 0xffff, // (213)
+ 0xffff, // (214)
+ 0xffff, // (215)
+ 0xffff, // (216)
+ 0xffff, // (217)
+ 0xffff, // (218)
+ MAC_LEFTBRACKET_KEY, // (219)
+ MAC_BACKSLASH_KEY, // (220)
+ MAC_RIGHTBRACKET_KEY, // (221)
+ MAC_APOSTROPHE_KEY, // (222)
+ 0xffff, // (223)
+ 0xffff, // (224)
+ 0xffff, // (225)
+ 0xffff, // (226)
+ 0xffff, // (227)
+ 0xffff, // (228)
+ 0xffff, // (229)
+ 0xffff, // (230)
+ 0xffff, // (231)
+ 0xffff, // (232)
+ 0xffff, // (233)
+ 0xffff, // (234)
+ 0xffff, // (235)
+ 0xffff, // (236)
+ 0xffff, // (237)
+ 0xffff, // (238)
+ 0xffff, // (239)
+ 0xffff, // (240)
+ 0xffff, // (241)
+ 0xffff, // (242)
+ 0xffff, // (243)
+ 0xffff, // (244)
+ 0xffff, // (245)
+ 0xffff, // (246)
+ 0xffff, // (247)
+ 0xffff, // (248)
+ 0xffff, // (249)
+ 0xffff, // (250)
+ 0xffff, // (251)
+ 0xffff, // (252)
+ 0xffff, // (253)
+ 0xffff, // (254)
+ 0xffff, // (255)
+ };
+
+
+ static KeyMap g_theKeys;
+
+ void SetKey( int key)
+ {
+ g_theKeys[ key >> 3] |= (1 << (key & 7));
+ }
+
+ void ClearKey( int key)
+ {
+ g_theKeys[ key >> 3] &= (0xff ^ (1 << (key & 7)));
+ }
+
+ void GetKeys( unsigned char theKeys[16])
+ {
+ memcpy( theKeys, &g_theKeys, 16);
+ }
+
+ Boolean Button()
+ {
+ return g_button;
+ }
+
+
+ void ClipMouseToWindow(HWND window)
+ {
+ RECT wRect;
+
+ GetClientRect(window, &wRect);
+
+ ClientToScreen(window, (LPPOINT)&wRect.left);
+ ClientToScreen(window, (LPPOINT)&wRect.right);
+
+ ClipCursor(&wRect);
+
+ return;
+ }
+
+ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
+ {
+ /* this is where we receive all messages concerning this window
+ * we can either process a message or pass it on to the default
+ * message handler of windows */
+
+ static PAINTSTRUCT ps;
+
+ switch(msg)
+ {
+ case WM_ACTIVATE: // Watch For Window Activate Message
+ {
+ // Check Minimization State
+ BOOL iconified = HIWORD(wParam) ? TRUE : FALSE;
+
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ ClipCursor(NULL);
+
+ if (fullscreen)
+ {
+ if( !iconified )
+ {
+ // Minimize window
+ CloseWindow( hWnd );
+
+ // The window is now iconified
+ iconified = GL_TRUE;
+ }
+ }
+
+ ShutdownDSp();
+
+ g_focused=false; // Program Is Active
+ }
+ else
+ {
+ SetupDSpFullScreen();
+
+ if( iconified )
+ {
+ // Minimize window
+ OpenIcon( hWnd );
+
+ // The window is now iconified
+ iconified = GL_FALSE;
+
+ // Activate window
+ ShowWindow( hWnd, SW_SHOW );
+ SetForegroundWindow( hWnd );
+ SetFocus( hWnd );
+ }
+
+ ClipMouseToWindow(hWnd);
+ g_focused=true; // Program Is No Longer Active
+ }
+
+ return 0; // Return To The Message Loop
+ }
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ // check for Alt-F4 (exit hotkey)
+ if (wParam == VK_F4)
+ {
+ if (GetKeyState( VK_MENU) & 0x8080)
+ {
+ gDone = true;
+ break;
+ }
+ }
+ if (wParam < MAX_WINKEYS)
+ {
+ if (KeyTable[wParam] != 0xffff)
+ SetKey( KeyTable[wParam]);
+ }
+ return (0);
+ }
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ if (wParam < MAX_WINKEYS)
+ if (KeyTable[wParam] != 0xffff)
+ ClearKey( KeyTable[wParam]);
+ return (0);
+ }
+
+ case WM_CHAR:
+ case WM_DEADCHAR:
+ case WM_SYSCHAR:
+ case WM_SYSDEADCHAR:
+ return (0);
+
+ case WM_NCLBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ {
+ g_button = true;
+ buttons[ 0] = true;
+ }
+ return (0);
+
+ case WM_NCRBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ buttons[ 1] = true;
+ }
+ return (0);
+
+ case WM_NCMBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ {
+ buttons[ 2] = true;
+ }
+ return (0);
+
+ case WM_NCLBUTTONUP:
+ case WM_LBUTTONUP:
+ {
+ g_button = false;
+ buttons[ 0] = false;
+ }
+ return (0);
+
+ case WM_NCRBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ buttons[ 1] = false;
+ }
+ return (0);
+
+ case WM_NCMBUTTONUP:
+ case WM_MBUTTONUP:
+ {
+ buttons[ 2] = false;
+ }
+ return (0);
+
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_LBUTTONDBLCLK:
+ return (0);
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ return (0);
+
+ case WM_NCMOUSEMOVE:
+ case WM_MOUSEMOVE:
+ /* ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseX = (signed short)(lParam & 0xffff);
+ ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseY = (signed short)(lParam >> 16);
+ if (g_lastWindow->m_mouseCallbacksEnabled) g_lastWindow->MouseMoveCallback();
+ */// goto winmessage;
+ return (0);
+
+ case WM_SYSCOMMAND: // Intercept System Commands
+ {
+ switch (wParam) // Check System Calls
+ {
+ case SC_SCREENSAVE: // Screensaver Trying To Start?
+ case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
+ return 0; // Prevent From Happening
+
+ // User trying to access application menu using ALT?
+ case SC_KEYMENU:
+ return 0;
+ }
+ }
+ break;
+
+ case WM_MOVE:
+// {
+// ReleaseCapture();
+// ClipMouseToWindow(hWnd);
+// }
+ break;
+
+ case WM_SIZE:
+ break;
+
+ case WM_CLOSE:
+ {
+ //gDone = true;
+ //game.tryquit=1;
+ }
+ //return (0);
+
+ case WM_DESTROY:
+ {
+ //ClipCursor(NULL);
+ PostQuitMessage(0); /* Terminate Application */
+ }
+ return (0);
+
+ case WM_ERASEBKGND:
+ break;
+
+ case WM_PAINT:
+// BeginPaint( g_windowHandle,&ps);
+// EndPaint( g_windowHandle,&ps);
+ break;
+
+ default:
+ break;
+ }
+
+ /* We processed the message and there
+ * is no processing by Windows necessary */
+
+ /* We didn't process the message so let Windows do it */
+ return DefWindowProc(hWnd,msg,wParam,lParam);
+ }
+
+
+ static BOOL RegisterWindowClasses(HINSTANCE hFirstInstance)
+ {
+ WNDCLASSEX wc;
+ memset( &wc, 0, sizeof( wc));
+
+ /* Register the window class. */
+ wc.cbSize = sizeof(wc);
+#undef style
+ wc.style = (CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC); /* Combination of Class Styles */
+ wc.lpfnWndProc = AppWndProc; /* Adress of Window Procedure */
+ wc.cbClsExtra = 0; /* Extra Bytes allocated for this Class */
+ wc.cbWndExtra = 0; /* Extra Bytes allocated for each Window */
+ wc.hInstance = hFirstInstance; /* Handle of program instance */
+ wc.hIcon = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) );
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = g_wndClassName; /* Name of the Window Class */
+ wc.hIconSm = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) );
+
+ if (!RegisterClassEx(&wc)) return FALSE; /* Register Class failed */
+
+ return TRUE;
+ }
+
+ int resolutionID(int width, int height)
+ {
+ int whichres;
+ whichres=-1;
+ if(width==640 && height==480)whichres=0;
+ if(width==800 && height==600)whichres=1;
+ if(width==1024 && height==768)whichres=2;
+ if(width==1280 && height==1024)whichres=3;
+ if(width==1600 && height==1200)whichres=4;
+ if(width==840 && height==524)whichres=5;
+ if(width==1024 && height==640)whichres=6;
+ if(width==1344 && height==840)whichres=7;
+
+ return whichres;
+ }
+
+ int closestResolution(int width, int height)
+ {
+ int whichres;
+ whichres=-1;
+ if(width>=640 && height>=480)whichres=0;
+ if(width>=800 && height>=600)whichres=1;
+ if(width>=1024 && height>=768)whichres=2;
+ if(width>=1280 && height>=1024)whichres=3;
+ if(width>=1600 && height>=1200)whichres=4;
+ if(width==840 && height==524)whichres=5;
+ if(width==1024 && height==640)whichres=6;
+ if(width==1344 && height==840)whichres=7;
+
+ return whichres;
+ }
+
+ bool selectDetail(int & width, int & height, int & bpp, int & detail)
+ {
+ bool res = true;
+ int whichres = closestResolution(width, height);
+
+ while (true)
+ {
+ if(whichres<=0 || whichres>7){
+ whichres = 0;
+ width=640;
+ height=480;
+ }
+ if(whichres==1){
+ width=800;
+ height=600;
+ }
+ if(whichres==2){
+ width=1024;
+ height=768;
+ }
+ if(whichres==3){
+ width=1280;
+ height=1024;
+ }
+ if(whichres==4){
+ width=1600;
+ height=1200;
+ }
+ if(whichres==5){
+ width=840;
+ height=524;
+ }
+ if(whichres==6){
+ width=1024;
+ height=640;
+ }
+ if(whichres==7){
+ width=1344;
+ height=840;
+ }
+
+ if ((detail != 0) && (resolutionDepths[whichres][1] != 0))
+ {
+ break;
+ }
+ else if ((detail == 0) && (resolutionDepths[whichres][0] != 0))
+ {
+ break;
+ }
+ else if ((detail != 0) && (resolutionDepths[whichres][0] != 0))
+ {
+ res = false;
+ detail = 0;
+ break;
+ }
+ else if (0 == whichres)
+ {
+ break;
+ }
+
+ --whichres;
+ }
+
+ bpp = resolutionDepths[whichres][(detail != 0)];
+
+ return res;
+ }
+
+ int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
+ {
+ int argc = 0;
+ LPWSTR * cl = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (argc > 1)
+ {
+ if (0 == _wcsicmp(cl[1], L"-windowed"))
+ {
+ fullscreen = false;
+ }
+ }
+
+ logger.start(true);
+
+ memset( &g_theKeys, 0, sizeof( KeyMap));
+
+ unsigned int i = 0;
+ DEVMODE mode;
+ memset(&mode, 0, sizeof(mode));
+ mode.dmSize = sizeof(mode);
+ while (EnumDisplaySettings(NULL, i++, &mode))
+ {
+ if (mode.dmBitsPerPel < 16)
+ {
+ continue;
+ }
+
+ int res = resolutionID(mode.dmPelsWidth, mode.dmPelsHeight);
+
+ if (res > -1 && res < 8)
+ {
+ if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&mode, CDS_TEST))
+ {
+ continue;
+ }
+
+ switch(mode.dmBitsPerPel)
+ {
+ case 32:
+ case 24:
+ resolutionDepths[res][1] = mode.dmBitsPerPel;
+ break;
+ case 16:
+ resolutionDepths[res][0] = mode.dmBitsPerPel;
+ break;
+ }
+ }
+ }
+
+ /* if there is no Instance of our program in memory then register the window class */
+ if (hPrevInstance == NULL && !RegisterWindowClasses(hInstance))
+ return FALSE; /* registration failed! */
+
+ g_appInstance=hInstance;
+
+ main();
+
+ UnregisterClass( g_wndClassName, hInstance);
+
+ return TRUE;
+
+ }
+
+ extern int channels[100];
+ extern FSOUND_SAMPLE * samp[100];
+ extern FSOUND_STREAM * strm[10];
+
+ extern "C" void PlaySoundEx(int chan, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused)
+ {
+ const FSOUND_SAMPLE * currSample = FSOUND_GetCurrentSample(channels[chan]);
+ if (currSample && currSample == samp[chan])
+ {
+ if (FSOUND_GetPaused(channels[chan]))
+ {
+ FSOUND_StopSound(channels[chan]);
+ channels[chan] = FSOUND_FREE;
+ }
+ else if (FSOUND_IsPlaying(channels[chan]))
+ {
+ int loop_mode = FSOUND_GetLoopMode(channels[chan]);
+ if (loop_mode & FSOUND_LOOP_OFF)
+ {
+ channels[chan] = FSOUND_FREE;
+ }
+ }
+ }
+ else
+ {
+ channels[chan] = FSOUND_FREE;
+ }
+
+ channels[chan] = FSOUND_PlaySoundEx(channels[chan], sptr, dsp, startpaused);
+ if (channels[chan] < 0)
+ {
+ channels[chan] = FSOUND_PlaySoundEx(FSOUND_FREE, sptr, dsp, startpaused);
+ }
+ }
+
+ extern "C" void PlayStreamEx(int chan, FSOUND_STREAM *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused)
+ {
+ const FSOUND_SAMPLE * currSample = FSOUND_GetCurrentSample(channels[chan]);
+ if (currSample && currSample == FSOUND_Stream_GetSample(sptr))
+ {
+ FSOUND_StopSound(channels[chan]);
+ FSOUND_Stream_Stop(sptr);
+ }
+ else
+ {
+ FSOUND_Stream_Stop(sptr);
+ channels[chan] = FSOUND_FREE;
+ }
+
+ channels[chan] = FSOUND_Stream_PlayEx(channels[chan], sptr, dsp, startpaused);
+ if (channels[chan] < 0)
+ {
+ channels[chan] = FSOUND_Stream_PlayEx(FSOUND_FREE, sptr, dsp, startpaused);
+ }
+ }
+
+ bool LoadImage(const char * fname, TGAImageRec & tex)
+ {
+ bool res = true;
+
+ if ( tex.data == NULL )
+ {
+ return false;
+ }
+
+ ILstring f = strdup(ConvertFileName(fname));
+ if (!f)
+ {
+ return false;
+ }
+
+ ILuint iid=0;
+ ilGenImages(1, &iid);
+ ilBindImage(iid);
+ if (ilLoadImage(f))
+ {
+ //iluFlipImage();
+ tex.sizeX = ilGetInteger(IL_IMAGE_WIDTH);
+ tex.sizeY = ilGetInteger(IL_IMAGE_HEIGHT);
+ tex.bpp = ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
+ ILuint Bpp = ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL),
+ imageSize = tex.sizeX * tex.sizeY * Bpp;
+ ILubyte *Data = ilGetData();
+ memcpy(tex.data, Data, imageSize);
+
+ // Truvision Targa files are stored as BGR colors
+ // We want RGB so Blue and Red bytes are switched
+ if (IL_TGA == ilGetInteger(IL_IMAGE_FORMAT))
+ {
+ // Loop Through The Image Data
+ for (GLuint i = 0; i < int(imageSize); i += Bpp)
+ {
+ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
+ GLbyte temp; // Temporary Variable
+ temp = tex.data[i]; // Temporarily Store The Value At Image Data 'i'
+ tex.data[i] = tex.data[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
+ tex.data[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
+ }
+ }
+ }
+ else
+ {
+ res = false;
+ }
+ ilDeleteImages(1, &iid);
+/*
+ if (tid)
+ {
+ GLuint texid = ilutGLLoadImage(f);
+ *tid = texid;
+ }
+ else if (mip)
+ {
+ ilutGLBuildMipmaps()
+ }
+ else
+ {
+ ilutGLTexImage(0);
+ }
+*/
+ free(f);
+
+ return res;
+ }
+
+ void ScreenShot(const char * fname)
+ {
+ ILstring f = strdup(fname);
+ if (!f)
+ {
+ return;
+ }
+
+ ILuint iid;
+ ilGenImages(1, &iid);
+ ilBindImage(iid);
+ if (ilutGLScreen())
+ {
+ ilSaveImage(f);
+ }
+ ilDeleteImages(1, &iid);
+
+ free(f);
+ }
--- /dev/null
+/**> HEADER FILES <**/
+#include "Person.h"
+
+extern float multiplier;
+extern Animation animation[animation_count];
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern Terrain terrain;
+extern float gravity;
+extern int environment;
+extern Sprites sprites;
+extern int detail;
+extern FRUSTUM frustum;
+extern XYZ viewer;
+extern float realmultiplier;
+extern int slomo;
+extern float slomodelay;
+extern bool cellophane;
+extern float texdetail;
+extern float realtexdetail;
+extern GLubyte bloodText[512*512*3];
+extern GLubyte wolfbloodText[512*512*3];
+extern int bloodtoggle;
+extern Objects objects;
+extern bool osx;
+extern bool autoslomo;
+extern float camerashake;
+extern float woozy;
+extern float terraindetail;
+extern float viewdistance;
+extern float blackout;
+extern int difficulty;
+extern Weapons weapons;
+extern bool decals;
+extern float fadestart;
+extern Person player[maxplayers];
+extern int numplayers;
+extern bool freeze;
+extern bool winfreeze;
+extern float flashamount,flashr,flashg,flashb;
+extern int flashdelay;
+extern bool showpoints;
+extern bool immediate;
+extern int test;
+extern bool tilt2weird;
+extern bool tiltweird;
+extern bool midweird;
+extern bool proportionweird;
+extern bool vertexweird[6];
+extern GLubyte texturearray[512*512*3];
+extern XYZ envsound[30];
+extern float envsoundvol[30];
+extern float envsoundlife[30];
+extern int numenvsounds;
+extern int bonus;
+extern float bonusvalue;
+extern float bonustotal;
+extern float bonustime;
+extern int tutoriallevel;
+extern float smoketex;
+extern int tutorialstage;
+extern bool reversaltrain;
+extern bool canattack;
+extern bool cananger;
+extern float damagedealt;
+extern float damagetaken;
+extern int hostile;
+extern float hostiletime;
+
+extern int mainmenu;
+
+extern int numfalls;
+extern int numflipfail;
+extern int numseen;
+extern int numswordattack;
+extern int numknifeattack;
+extern int numunarmedattack;
+extern int numescaped;
+extern int numflipped;
+extern int numwallflipped;
+extern int numthrowkill;
+extern int numafterkill;
+extern int numreversals;
+extern int numattacks;
+extern int maxalarmed;
+extern int indialogue;
+
+extern bool gamestarted;
+
+extern FSOUND_STREAM * strm[10];
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+extern "C" void PlayStreamEx(int chan, FSOUND_STREAM *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+void Person::CheckKick(){
+ static XYZ relative;
+ static int i;
+
+ float damagemult=1*power;
+ if(creature==wolftype)damagemult=2.5*power;
+ damagemult*=power;
+
+ if(hasvictim)
+ if(targetanimation==rabbitkickanim&&victim&&victim!=this&¤tframe>=2&¤tanimation==rabbitkickanim){
+ if(findDistancefast(&coords,&victim->coords)<1.2){
+ if(!victim->skeleton.free){
+ relative=velocity;
+ Normalise(&relative);
+ relative=coords+relative*1;
+ if(animation[victim->targetanimation].height!=lowheight){
+ victim->spurt=1;
+ DoBlood(.2,250);
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ victim->RagDoll(0);
+ relative=velocity;
+ relative.y=0;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*120*damagemult;
+ }
+ victim->Puff(neck);
+ victim->DoDamage(100*damagemult/victim->protectionhigh);
+ if(id==0)camerashake+=.4;
+
+ target=0;
+ currentframe=3;
+ targetanimation=backflipanim;
+ targetframe=4;
+ velocity=facing*-10;
+ velocity.y=5;
+ skeleton.free=0;
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], FALSE);
+
+ //if(victim->damage>victim->damagetolerance){
+ if(id==0){
+ bonus=cannon;
+ bonustime=0;
+ bonusvalue=100;
+ }
+ //}
+ }
+ else if (victim->isCrouch()){
+ targetanimation=rabbitkickreversedanim;
+ currentanimation=rabbitkickreversedanim;
+ victim->currentanimation=rabbitkickreversalanim;
+ victim->targetanimation=rabbitkickreversalanim;
+ targettilt2=0;
+ currentframe=0;
+ targetframe=1;
+ target=0;
+ velocity=0;
+ victim->oldcoords=victim->coords;
+ coords=victim->coords;
+ victim->targetrotation=targetrotation;
+ victim->victim=this;
+ }
+ }
+ }
+ }
+}
+
+void Person::CatchFire(){
+ XYZ flatfacing,flatvelocity;
+ int howmany;
+ for(int i=0;i<10;i++){
+ howmany=abs(Random()%(skeleton.num_joints));
+ if(!skeleton.free)flatvelocity=velocity;
+ if(skeleton.free)flatvelocity=skeleton.joints[howmany].velocity;
+ if(!skeleton.free)flatfacing=DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position,0,0,tilt),tilt2,0,0),0,rotation,0)*scale+coords;
+ if(skeleton.free)flatfacing=skeleton.joints[howmany].position*scale+coords;
+ sprites.MakeSprite(flamesprite, flatfacing,flatvelocity, 1,1,1, 2, 1);
+ }
+
+ onfiredelay=0.5;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ //PlaySoundEx( firesound, samp[firesound], NULL, TRUE);
+ PlayStreamEx( stream_firesound, strm[stream_firesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[stream_firesound], gLoc, vel);
+ FSOUND_SetVolume(channels[stream_firesound], 256);
+ FSOUND_SetPaused(channels[stream_firesound], FALSE);
+
+ flamedelay=0;
+
+ onfire=1;
+}
+
+bool Person::isIdle(){
+ if(targetanimation==sleepanim||targetanimation==sitanim||targetanimation==talkidleanim||targetanimation==hurtidleanim||targetanimation==bounceidleanim||targetanimation==talkidleanim||targetanimation==fightidleanim||targetanimation==knifefightidleanim||targetanimation==swordfightidleanim||targetanimation==swordfightidlebothanim||targetanimation==fightsidestep||targetanimation==wolfidle)return 1;
+ else return 0;
+}
+
+bool Person::isSitting(){
+ if(targetanimation==sitanim)return 1;
+ if(targetanimation==sitwallanim)return 1;
+ else return 0;
+}
+
+bool Person::isSleeping(){
+ if(targetanimation==sleepanim)return 1;
+ if(targetanimation==dead1anim)return 1;
+ if(targetanimation==dead2anim)return 1;
+ if(targetanimation==dead3anim)return 1;
+ if(targetanimation==dead4anim)return 1;
+ else return 0;
+}
+
+bool Person::wasIdle(){
+ if(currentanimation==sleepanim||currentanimation==talkidleanim||currentanimation==sitanim||currentanimation==hurtidleanim||currentanimation==bounceidleanim||currentanimation==fightidleanim||currentanimation==swordfightidleanim||currentanimation==swordfightidlebothanim||currentanimation==knifefightidleanim||currentanimation==fightsidestep||currentanimation==wolfidle)return 1;
+ else return 0;
+}
+int Person::getIdle(){
+ if(indialogue!=-1&&howactive==typeactive&&creature==rabbittype)return talkidleanim;
+ if(hasvictim&&victim!=this/*||(id==0&&attackkeydown)*/)if(/*(id==0&&attackkeydown)||*/(!victim->dead&&victim->aitype!=passivetype&&victim->aitype!=searchtype&&aitype!=passivetype&&aitype!=searchtype&&victim->id<numplayers)){
+ if((aitype==playercontrolled&&stunned<=0&&weaponactive==-1)||pause){
+ if(creature==rabbittype)return fightidleanim;
+ if(creature==wolftype)return wolfidle;
+ }
+ if(aitype==playercontrolled&&stunned<=0&&weaponactive!=-1){
+ if(weapons.type[weaponids[weaponactive]]==knife)return knifefightidleanim;
+ if(weapons.type[weaponids[weaponactive]]==sword&&victim->weaponactive!=-1)return swordfightidlebothanim;
+ if(weapons.type[weaponids[weaponactive]]==sword)return swordfightidleanim;
+ if(weapons.type[weaponids[weaponactive]]==staff)return swordfightidleanim;
+ }
+ if(aitype!=playercontrolled&&stunned<=0&&creature!=wolftype&&!pause)return fightsidestep;
+ }
+ if((damage>permanentdamage||damage>damagetolerance*.8||deathbleeding>0)&&creature!=wolftype)return hurtidleanim;
+ if(howactive==typesitting)return sitanim;
+ if(howactive==typesittingwall)return sitwallanim;
+ if(howactive==typesleeping)return sleepanim;
+ if(howactive==typedead1)return dead1anim;
+ if(howactive==typedead2)return dead2anim;
+ if(howactive==typedead3)return dead3anim;
+ if(howactive==typedead4)return dead4anim;
+ if(creature==rabbittype)return bounceidleanim;
+ if(creature==wolftype)return wolfidle;
+ return 0;
+}
+
+bool Person::isCrouch(){
+ if(targetanimation==crouchanim||targetanimation==wolfcrouchanim)return 1;
+ else return 0;
+}
+
+
+bool Person::wasCrouch(){
+ if(currentanimation==crouchanim||currentanimation==wolfcrouchanim)return 1;
+ else return 0;
+}
+int Person::getCrouch(){
+ if(creature==rabbittype)return crouchanim;
+ if(creature==wolftype)return wolfcrouchanim;
+ return 0;
+}
+
+bool Person::isRun(){
+ if(targetanimation==runanim||targetanimation==wolfrunanim||targetanimation==wolfrunninganim||targetanimation==rabbitrunninganim)return 1;
+ else return 0;
+}
+
+
+bool Person::wasRun(){
+ if(currentanimation==runanim||currentanimation==wolfrunanim||currentanimation==wolfrunninganim||currentanimation==rabbitrunninganim)return 1;
+ else return 0;
+}
+int Person::getRun(){
+ if(creature==rabbittype&&(!superruntoggle||weaponactive!=-1))return runanim;
+ if(creature==wolftype&&(!superruntoggle))return wolfrunanim;
+
+ if(creature==rabbittype&&(superruntoggle&&weaponactive==-1))return rabbitrunninganim;
+ if(creature==wolftype&&(superruntoggle))return wolfrunninganim;
+ return 0;
+}
+
+bool Person::isStop(){
+ if(targetanimation==stopanim||targetanimation==wolfstopanim)return 1;
+ else return 0;
+}
+
+
+bool Person::wasStop(){
+ if(currentanimation==stopanim||currentanimation==wolfstopanim)return 1;
+ else return 0;
+}
+int Person::getStop(){
+ if(creature==rabbittype)return stopanim;
+ if(creature==wolftype)return wolfstopanim;
+ return 0;
+}
+
+
+bool Person::isLanding(){
+ if(targetanimation==landanim||targetanimation==wolflandanim)return 1;
+ else return 0;
+}
+
+
+bool Person::wasLanding(){
+ if(currentanimation==landanim||currentanimation==wolflandanim)return 1;
+ else return 0;
+}
+int Person::getLanding(){
+ if(creature==rabbittype)return landanim;
+ if(creature==wolftype)return wolflandanim;
+ return 0;
+}
+
+
+bool Person::isLandhard(){
+ if(targetanimation==landhardanim||targetanimation==wolflandhardanim)return 1;
+ else return 0;
+}
+
+
+bool Person::wasLandhard(){
+ if(currentanimation==landhardanim||currentanimation==wolflandhardanim)return 1;
+ else return 0;
+}
+int Person::getLandhard(){
+ if(creature==rabbittype)return landhardanim;
+ if(creature==wolftype)return wolflandhardanim;
+ return 0;
+}
+
+
+bool Person::isFlip(){
+ if(targetanimation==flipanim||targetanimation==frontflipanim||targetanimation==backflipanim||targetanimation==rightflipanim||targetanimation==leftflipanim||targetanimation==walljumprightkickanim||targetanimation==walljumpleftkickanim)return 1;
+ else return 0;
+}
+
+bool Person::wasFlip(){
+ if(currentanimation==flipanim||currentanimation==frontflipanim||currentanimation==backflipanim||currentanimation==rightflipanim||currentanimation==leftflipanim||currentanimation==walljumprightkickanim||currentanimation==walljumpleftkickanim)return 1;
+ else return 0;
+}
+
+bool Person::isWallJump(){
+ if(targetanimation==walljumpfrontanim||targetanimation==walljumpbackanim||targetanimation==walljumpleftanim||targetanimation==walljumprightanim)return 1;
+ else return 0;
+}
+
+void SolidHitBonus();
+void SolidHitBonus(){
+ if(bonustime<1.5&&(bonus==fourxcombo||bonus==megacombo)){
+ bonus=megacombo;
+ bonustime=0;
+ bonusvalue=160;
+ }
+ else if(bonustime<1.5&&bonus==threexcombo){
+ bonus=fourxcombo;
+ bonustime=0;
+ bonusvalue=80;
+ }
+ else if(bonustime<1.5&&bonus==twoxcombo){
+ bonus=threexcombo;
+ bonustime=0;
+ bonusvalue=40;
+ }
+ else if(bonustime<1.5&&bonus==solidhit){
+ bonus=twoxcombo;
+ bonustime=0;
+ bonusvalue=20;
+ }
+ else {
+ bonus=solidhit;
+ bonustime=0;
+ bonusvalue=10;
+ }
+}
+
+void Person::DoBlood(float howmuch,int which){
+ static int bleedxint,bleedyint;
+ static XYZ bloodvel;
+ //if(howmuch&&id==0)blooddimamount=1;
+ if(bloodtoggle&&tutoriallevel!=1){
+ if(bleeding<=0&&spurt){
+ spurt=0;
+ for(int i=0;i<3;i++){
+ bloodvel=0;
+ if(!skeleton.free){
+ bloodvel.z=10;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ }
+ if(skeleton.free){
+ bloodvel-=DoRotation(skeleton.forward*10*scale,((float)(Random()%100))/4,((float)(Random()%100))/4,0);
+ }
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/4,((float)(Random()%100))/4,0)*scale;
+ if(skeleton.free){
+ sprites.MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ if(!skeleton.free){
+ sprites.MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ }
+ if(Random()%2==0)
+ for(int i=0;i<3;i++){
+ if(Random()%2!=0){
+ bloodvel=0;
+ if(!skeleton.free){
+ bloodvel.z=10;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ }
+ if(skeleton.free){
+ bloodvel-=DoRotation(skeleton.forward*10*scale,((float)(Random()%100))/4,((float)(Random()%100))/4,0);
+ }
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/4,((float)(Random()%100))/4,0)*scale;
+ bloodvel*=.2;
+ if(skeleton.free){
+ sprites.MakeSprite(splintersprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.special[sprites.numsprites-1]=3;
+ }
+ if(!skeleton.free){
+ sprites.MakeSprite(splintersprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.special[sprites.numsprites-1]=3;
+ }
+ }
+ }
+ }
+ if(decals){
+ bleeding=howmuch+(float)abs(Random()%100)/200-.25;
+ bleedxint=0;
+ bleedyint=0;
+ int texdetailint=realtexdetail;
+ if(creature==rabbittype)
+ while(bloodText[bleedxint*512*3+bleedyint*3+0]>which+4||bloodText[bleedxint*512*3+bleedyint*3+0]<which-4||bleedxint<10||bleedyint<10||bleedxint>500||bleedyint>500){
+ bleedxint=abs(Random()%512);
+ bleedyint=abs(Random()%512);
+ }
+ if(creature==wolftype)
+ while(wolfbloodText[bleedxint*512*3+bleedyint*3+0]>which+4||wolfbloodText[bleedxint*512*3+bleedyint*3+0]<which-4||bleedxint<10||bleedyint<10||bleedxint>500||bleedyint>500){
+ bleedxint=abs(Random()%512);
+ bleedyint=abs(Random()%512);
+ }
+ bleedy=bleedxint;
+ bleedx=bleedyint;
+ bleedy/=realtexdetail;
+ bleedx/=realtexdetail;
+ direction=abs(Random()%2)*2-1;
+ }
+
+ }
+ if(bleeding>2)bleeding=2;
+}
+
+void Person::DoBloodBig(float howmuch,int which){
+ static int bleedxint,bleedyint,i,j;
+ static XYZ bloodvel;
+ if(howmuch&&id==0)blooddimamount=1;
+
+ if(tutoriallevel!=1||id==0)
+ if(aitype!=playercontrolled&&howmuch>0){
+ int whichsound=-1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(creature==wolftype){
+ int i=abs(Random()%2);
+ if(i==0)whichsound=snarlsound;
+ if(i==1)whichsound=snarl2sound;
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ if(creature==rabbittype){
+ int i=abs(Random()%2);
+ if(i==0)whichsound=rabbitpainsound;
+ if(i==1&&howmuch>=2)whichsound=rabbitpain1sound;
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ //if(i==2)whichsound=rabbitpain2sound;
+ }
+
+ if(whichsound!=-1){
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 512);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+ if(id==0&&howmuch>0){
+ flashamount=.5;
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashdelay=0;
+ }
+
+ if(bloodtoggle&&decals&&tutoriallevel!=1){
+ if(bleeding<=0&&spurt){
+ spurt=0;
+ for(int i=0;i<3;i++){
+ bloodvel=0;
+ if(!skeleton.free){
+ bloodvel.z=10;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ }
+ if(skeleton.free){
+ bloodvel-=DoRotation(skeleton.forward*10*scale,((float)(Random()%100))/4,((float)(Random()%100))/4,0);
+ }
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/4,((float)(Random()%100))/4,0)*scale;
+ if(skeleton.free){
+ sprites.MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ if(!skeleton.free){
+ sprites.MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ }
+ }
+ int offsetx=0,offsety=0;
+ if(which==225){
+ offsety=Random()%40;
+ offsetx=abs(Random()%60);
+ }
+ if(which==190||which==185){
+ offsety=Random()%40;
+ offsetx=abs(Random()%100)-20;
+ }
+ if(which==175){
+ offsety=Random()%10;
+ offsetx=Random()%10;
+ }
+ if(which==170){
+ offsety=Random()%20;
+ offsetx=Random()%20;
+ }
+ if(which==220||which==215){
+ //offsety=Random()%20;
+ offsetx=20;
+ //offsetx=abs(Random()%80);
+ }
+
+
+ int startx=512;
+ int starty=512;
+ int endx=0;
+ int endy=0;
+ GLubyte color;
+ if(creature==rabbittype)
+ for(i=0;i<512;i++){
+ for(j=0;j<512;j++){
+ if(bloodText[i*512*3+j*3+0]<=which+4&&bloodText[i*512*3+j*3+0]>=which-4){
+ if(i<startx)startx=i;
+ if(j<starty)starty=j;
+ if(i>endx)endx=i;
+ if(j>endy)endy=j;
+ }
+ }
+ }
+ if(creature==wolftype)
+ for(i=0;i<512;i++){
+ for(j=0;j<512;j++){
+ if(wolfbloodText[i*512*3+j*3+0]<=which+4&&wolfbloodText[i*512*3+j*3+0]>=which-4){
+ if(i<startx)startx=i;
+ if(j<starty)starty=j;
+ if(i>endx)endx=i;
+ if(j>endy)endy=j;
+ }
+ }
+ }
+
+ startx+=offsetx;
+ endx+=offsetx;
+ starty+=offsety;
+ endy+=offsety;
+
+ if(startx<0)startx=0;
+ if(starty<0)starty=0;
+ if(endx>512-1)endx=512-1;
+ if(endy>512-1)endy=512-1;
+ if(endx<startx)endx=startx;
+ if(endy<starty)endy=starty;
+
+ startx/=realtexdetail;
+ starty/=realtexdetail;
+ endx/=realtexdetail;
+ endy/=realtexdetail;
+
+ int texdetailint=realtexdetail;
+ int where;
+ if(creature==rabbittype)
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ if(bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=which+4&&bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=which-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ }
+ }
+ if(creature==wolftype)
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ if(wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=which+4&&wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=which-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D,skeleton.drawmodel.textureptr);
+ if(detail!=2||osx)DoMipmaps(5,0,0,skeleton.skinsize,skeleton.skinsize);
+ else DoMipmaps(0,startx/realtexdetail,endx/realtexdetail,starty/realtexdetail,endy/realtexdetail);
+
+ bleedxint=0;
+ bleedyint=0;
+ if(creature==rabbittype)
+ while(bloodText[bleedxint*512*3+bleedyint*3+0]>which+4||bloodText[bleedxint*512*3+bleedyint*3+0]<which-4||bleedxint<10||bleedyint<10||bleedxint>500||bleedyint>500){
+ bleedxint=abs(Random()%512);
+ bleedyint=abs(Random()%512);
+ }
+ if(creature==wolftype)
+ while(wolfbloodText[bleedxint*512*3+bleedyint*3+0]>which+4||wolfbloodText[bleedxint*512*3+bleedyint*3+0]<which-4||bleedxint<10||bleedyint<10||bleedxint>500||bleedyint>500){
+ bleedxint=abs(Random()%512);
+ bleedyint=abs(Random()%512);
+ }
+ bleedy=bleedxint+offsetx;
+ bleedx=bleedyint+offsety;
+ bleedy/=realtexdetail;
+ bleedx/=realtexdetail;
+ if(bleedx<0)bleedx=0;
+ if(bleedy<0)bleedy=0;
+ if(bleedx>skeleton.skinsize-1)bleedx=skeleton.skinsize-1;
+ if(bleedy>skeleton.skinsize-1)bleedy=skeleton.skinsize-1;
+ direction=abs(Random()%2)*2-1;
+
+ }
+ bleeding=howmuch+(float)abs(Random()%100)/200-.25;
+ deathbleeding+=bleeding;
+ bloodloss+=bleeding*3;
+
+ if(tutoriallevel!=1&&aitype!=playercontrolled&&bloodloss>damagetolerance*2/3&&bloodloss<damagetolerance&&creature==rabbittype){
+ if(abs(Random()%2)==0){aitype=gethelptype;
+ lastseentime=12;
+ }
+ else aitype=attacktypecutoff;
+ ally=0;
+ }
+ if(bleeding>2)bleeding=2;
+}
+
+bool Person::DoBloodBigWhere(float howmuch,int which, XYZ where){
+ static int bleedxint,bleedyint,i,j;
+ static XYZ bloodvel;
+ static XYZ startpoint,endpoint,colpoint,movepoint;
+ static float rotationpoint;
+ static int whichtri;
+ static XYZ p1,p2,p3,p0;
+ static XYZ N,temp;
+ XYZ bary;
+ XYZ gxx,gyy;
+ float coordsx,coordsy;
+ float total;
+
+ if(bloodtoggle&&decals&&tutoriallevel!=1){
+ where-=coords;
+ if(!skeleton.free)where=DoRotation(where,0,-rotation,0);
+ //where=scale;
+ startpoint=where;
+ startpoint.y+=100;
+ endpoint=where;
+ endpoint.y-=100;
+ movepoint=0;
+ rotationpoint=0;
+ whichtri=skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &colpoint, &movepoint, &rotationpoint);
+ if(whichtri!=-1){
+ p0=colpoint;
+ p1=skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[0]];
+ p2=skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[1]];
+ p3=skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[whichtri].vertex[2]];
+ /*
+ CrossProduct(p2-p1,p3-p1,&N);
+ CrossProduct(p0-p1,p3-p1,&temp);
+ s = dotproduct(&temp,&N)/findLength(&N);
+ CrossProduct(p2-p1,p1-p0,&temp);
+ t = dotproduct(&temp,&N)/findLength(&N);
+ r = 1 - (s + t);*/
+
+ bary.x=findDistancefast(&p0,&p1);
+ bary.y=findDistancefast(&p0,&p2);
+ bary.z=findDistancefast(&p0,&p3);
+
+ total=bary.x+bary.y+bary.z;
+ bary.x/=total;
+ bary.y/=total;
+ bary.z/=total;
+
+ bary.x=1-bary.x;
+ bary.y=1-bary.y;
+ bary.z=1-bary.z;
+
+ total=bary.x+bary.y+bary.z;
+ bary.x/=total;
+ bary.y/=total;
+ bary.z/=total;
+
+
+ gxx.x=skeleton.drawmodel.Triangles[whichtri].gx[0];
+ gxx.y=skeleton.drawmodel.Triangles[whichtri].gx[1];
+ gxx.z=skeleton.drawmodel.Triangles[whichtri].gx[2];
+ gyy.x=skeleton.drawmodel.Triangles[whichtri].gy[0];
+ gyy.y=skeleton.drawmodel.Triangles[whichtri].gy[1];
+ gyy.z=skeleton.drawmodel.Triangles[whichtri].gy[2];
+ coordsx=skeleton.drawmodel.Triangles[whichtri].gx[0]*bary.x+skeleton.drawmodel.Triangles[whichtri].gx[1]*bary.y+skeleton.drawmodel.Triangles[whichtri].gx[2]*bary.z;
+ coordsy=skeleton.drawmodel.Triangles[whichtri].gy[0]*bary.x+skeleton.drawmodel.Triangles[whichtri].gy[1]*bary.y+skeleton.drawmodel.Triangles[whichtri].gy[2]*bary.z;
+
+ //coordsx=skeleton.drawmodel.Triangles[whichtri].gx[1];
+ //coordsy=skeleton.drawmodel.Triangles[whichtri].gy[1];
+
+ if(bleeding<=0&&spurt){
+ spurt=0;
+ for(int i=0;i<3;i++){
+ bloodvel=0;
+ if(!skeleton.free){
+ bloodvel.z=10;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ }
+ if(skeleton.free){
+ bloodvel-=DoRotation(skeleton.forward*10*scale,((float)(Random()%100))/4,((float)(Random()%100))/4,0);
+ }
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/4,((float)(Random()%100))/4,0)*scale;
+ if(skeleton.free){
+ sprites.MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, skeleton.joints[skeleton.jointlabels[head]].position*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ if(!skeleton.free){
+ sprites.MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ sprites.MakeSprite(bloodflamesprite, DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .3, 1);
+ }
+ }
+ }
+ int offsetx=0,offsety=0;
+ /*if(which==225){
+ offsety=Random()%40;
+ offsetx=abs(Random()%120);
+ }
+ if(which==220||which==215){
+ offsety=Random()%20;
+ offsetx=abs(Random()%80);
+ }*/
+ //which=220;
+ offsetx=(1+coordsy)*512-291;
+ offsety=coordsx*512-437;
+
+ int startx=512;
+ int starty=512;
+ int endx=0;
+ int endy=0;
+ GLubyte color;
+ if(creature==rabbittype)
+ for(i=0;i<512;i++){
+ for(j=0;j<512;j++){
+ if(bloodText[i*512*3+j*3+0]<=which+4&&bloodText[i*512*3+j*3+0]>=which-4){
+ if(i<startx)startx=i;
+ if(j<starty)starty=j;
+ if(i>endx)endx=i;
+ if(j>endy)endy=j;
+ }
+ }
+ }
+ if(creature==wolftype)
+ for(i=0;i<512;i++){
+ for(j=0;j<512;j++){
+ if(wolfbloodText[i*512*3+j*3+0]<=which+4&&wolfbloodText[i*512*3+j*3+0]>=which-4){
+ if(i<startx)startx=i;
+ if(j<starty)starty=j;
+ if(i>endx)endx=i;
+ if(j>endy)endy=j;
+ }
+ }
+ }
+ startx+=offsetx;
+ endx+=offsetx;
+ starty+=offsety;
+ endy+=offsety;
+
+ if(startx<0)startx=0;
+ if(starty<0)starty=0;
+ if(endx>512-1)endx=512-1;
+ if(endy>512-1)endy=512-1;
+ if(endx<startx)endx=startx;
+ if(endy<starty)endy=starty;
+
+ startx/=realtexdetail;
+ starty/=realtexdetail;
+ endx/=realtexdetail;
+ endy/=realtexdetail;
+
+ int texdetailint=realtexdetail;
+ int where;
+ if(creature==rabbittype)
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ if(bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=which+4&&bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=which-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ else if(bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=160+4&&bloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=160-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ }
+ }
+ if(creature==wolftype)
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ if(wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=which+4&&wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=which-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ else if(wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]<=160+4&&wolfbloodText[(i*texdetailint-offsetx)*512*3+(j*texdetailint-offsety)*3+0]>=160-4){
+ color=Random()%85+170;
+ where=i*skeleton.skinsize*3+j*3;
+ if(skeleton.skinText[where+0]>color/2)skeleton.skinText[where+0]=color/2;
+ skeleton.skinText[where+1]=0;
+ skeleton.skinText[where+2]=0;
+ }
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D,skeleton.drawmodel.textureptr);
+ if(detail!=2||osx)DoMipmaps(5,0,0,skeleton.skinsize,skeleton.skinsize);
+ else DoMipmaps(0,startx/realtexdetail,endx/realtexdetail,starty/realtexdetail,endy/realtexdetail);
+
+ bleedy=(1+coordsy)*512;
+ bleedx=coordsx*512;
+ bleedy/=realtexdetail;
+ bleedx/=realtexdetail;
+ if(bleedx<0)bleedx=0;
+ if(bleedy<0)bleedy=0;
+ if(bleedx>skeleton.skinsize-1)bleedx=skeleton.skinsize-1;
+ if(bleedy>skeleton.skinsize-1)bleedy=skeleton.skinsize-1;
+ direction=abs(Random()%2)*2-1;
+ }
+ if(whichtri==-1)return 0;
+ }
+ bleeding=howmuch+(float)abs(Random()%100)/200-.25;
+ deathbleeding+=bleeding;
+ bloodloss+=bleeding*3;
+
+ if(tutoriallevel!=1&&aitype!=playercontrolled&&bloodloss>damagetolerance*2/3&&bloodloss<damagetolerance&&creature==rabbittype){
+ if(abs(Random()%2)==0){aitype=gethelptype;
+ lastseentime=12;
+ }
+ else aitype=attacktypecutoff;
+ ally=0;
+ }
+ if(bleeding>2)bleeding=2;
+ return 1;
+}
+
+
+void Person::DoMipmaps(int howmanylevels,float startx, float endx, float starty, float endy){
+ int i,j,k;
+ static float temp;
+ static int bytesPerPixel=3;
+ static int newsize,totalsize,rowsize,bigstep,smallstep,sum;
+ static int newstartx,newstarty,newendx,newendy;
+ static int newnewstartx,newnewstarty,newnewendx,newnewendy;
+ static int which;
+ static float sizemult;
+ /*
+ for(i=0;i<skeleton.skinsize*skeleton.skinsize*bytesPerPixel;i++){
+ texture[i]=skeleton.skinText[i];
+ }
+ */
+ if((!osx||howmanylevels)){
+
+ if(startx<0)startx=0;
+ if(starty<0)starty=0;
+ if(endx>skeleton.skinsize-1)endx=skeleton.skinsize-1;
+ if(endy>skeleton.skinsize-1)endy=skeleton.skinsize-1;
+ if((endx>startx&&endy>starty)||howmanylevels){
+
+ newstartx=startx;
+ newstarty=starty;
+ newendx=endx;
+ newendy=endy;
+
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ texturearray[(i-newstartx)*(newendy-newstarty)*3+(j-newstarty)*3+0]=skeleton.skinText[i*skeleton.skinsize*3+j*3+0];
+ texturearray[(i-newstartx)*(newendy-newstarty)*3+(j-newstarty)*3+1]=skeleton.skinText[i*skeleton.skinsize*3+j*3+1];
+ texturearray[(i-newstartx)*(newendy-newstarty)*3+(j-newstarty)*3+2]=skeleton.skinText[i*skeleton.skinsize*3+j*3+2];
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D,skeleton.drawmodel.textureptr);
+
+ if(!howmanylevels){
+ if(!osx)glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,GL_TRUE);
+ glTexSubImage2D(GL_TEXTURE_2D,0,starty,startx,endy-starty,endx-startx,GL_RGB,GL_UNSIGNED_BYTE,texturearray);
+ if(!osx)glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,GL_FALSE);
+ }
+
+ newsize=skeleton.skinsize;
+
+ if(howmanylevels)
+ gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, skeleton.skinsize, skeleton.skinsize, GL_RGB, GL_UNSIGNED_BYTE, &skeleton.skinText[0] );
+ }
+ /*for(j=1;j<=howmanylevels;j++){
+ if(j==1)texpointer=&skeleton.skinText[0];
+ else texpointer=&texture[0];
+
+ totalsize=int( newsize*newsize*bytesPerPixel);
+ rowsize=int( newsize*bytesPerPixel );
+ bigstep=bytesPerPixel*newsize*2;
+ smallstep=bytesPerPixel*2;
+
+ which=0;
+
+
+
+ glTexSubImage2D(GL_TEXTURE_2D,j,0,0,newsize/2,newsize/2,GL_RGB,GL_UNSIGNED_BYTE,texture);
+ newsize/=2;
+ }*/
+ }
+}
+
+
+void Person::Reverse(){
+ if(victim->aitype==playercontrolled||hostiletime>1)
+ if(victim->targetanimation!=jumpupanim&&victim->targetanimation!=jumpdownanim&&((tutoriallevel!=1||cananger)&&hostile)){
+ if(normaldotproduct(victim->facing,victim->coords-coords)>0&&!(victim->id==0&&difficulty<2)&&(creature!=wolftype||victim->creature==wolftype))return;
+ if(victim->aitype!=playercontrolled&&staggerdelay>0)return;
+ if(targetanimation==sweepanim){
+ targetanimation=sweepreversedanim;
+ currentanimation=sweepreversedanim;
+ victim->currentanimation=sweepreversalanim;
+ victim->targetanimation=sweepreversalanim;
+ }
+ if(targetanimation==spinkickanim){
+ targetanimation=spinkickreversedanim;
+ currentanimation=spinkickreversedanim;
+ victim->currentanimation=spinkickreversalanim;
+ victim->targetanimation=spinkickreversalanim;
+ }
+ if(targetanimation==upunchanim||targetanimation==rabbittacklinganim){
+ if(targetanimation==rabbittacklinganim){
+ currentframe=6;
+ targetframe=7;
+ victim->currentframe=6;
+ victim->targetframe=7;
+ }
+ targetanimation=upunchreversedanim;
+ currentanimation=upunchreversedanim;
+ victim->currentanimation=upunchreversalanim;
+ victim->targetanimation=upunchreversalanim;
+ }
+ if(targetanimation==staffhitanim&&findDistancefast(&victim->coords,&coords)<2&&((victim->id==0&&victim->crouchkeydown)||Random()%4==0)){
+ if(victim->weaponactive!=-1){
+ victim->throwtogglekeydown=1;
+ weapons.owner[victim->weaponids[0]]=-1;
+ weapons.velocity[victim->weaponids[0]]=victim->velocity*.2;
+ if(weapons.velocity[victim->weaponids[0]].x==0)weapons.velocity[victim->weaponids[0]].x=.1;
+ weapons.tipvelocity[victim->weaponids[0]]=weapons.velocity[victim->weaponids[0]];
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[victim->num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+
+ victim->weaponactive=-1;
+ for(int j=0;j<numplayers;j++){
+ player[j].wentforweapon=0;
+ }
+ }
+
+ targetanimation=staffhitreversedanim;
+ currentanimation=staffhitreversedanim;
+ victim->currentanimation=staffhitreversalanim;
+ victim->targetanimation=staffhitreversalanim;
+ }
+ if(targetanimation==staffspinhitanim&&findDistancefast(&victim->coords,&coords)<2&&((victim->id==0&&victim->crouchkeydown)||Random()%2==0)){
+ if(victim->weaponactive!=-1){
+ victim->throwtogglekeydown=1;
+ weapons.owner[victim->weaponids[0]]=-1;
+ weapons.velocity[victim->weaponids[0]]=victim->velocity*.2;
+ if(weapons.velocity[victim->weaponids[0]].x==0)weapons.velocity[victim->weaponids[0]].x=.1;
+ weapons.tipvelocity[victim->weaponids[0]]=weapons.velocity[victim->weaponids[0]];
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[victim->num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+
+ victim->weaponactive=-1;
+ for(int j=0;j<numplayers;j++){
+ player[j].wentforweapon=0;
+ }
+ }
+ targetanimation=staffspinhitreversedanim;
+ currentanimation=staffspinhitreversedanim;
+ victim->currentanimation=staffspinhitreversalanim;
+ victim->targetanimation=staffspinhitreversalanim;
+ }
+ if(targetanimation==swordslashanim&&findDistancefast(&victim->coords,&coords)<2&&((victim->id==0&&victim->crouchkeydown)||Random()%4==0)){
+ if(victim->weaponactive!=-1){
+ victim->throwtogglekeydown=1;
+ weapons.owner[victim->weaponids[0]]=-1;
+ weapons.velocity[victim->weaponids[0]]=victim->velocity*.2;
+ if(weapons.velocity[victim->weaponids[0]].x==0)weapons.velocity[victim->weaponids[0]].x=.1;
+ weapons.tipvelocity[victim->weaponids[0]]=weapons.velocity[victim->weaponids[0]];
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[victim->num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+
+ victim->weaponactive=-1;
+ for(int j=0;j<numplayers;j++){
+ player[j].wentforweapon=0;
+ }
+ }
+ targetanimation=swordslashreversedanim;
+ currentanimation=swordslashreversedanim;
+ victim->currentanimation=swordslashreversalanim;
+ victim->targetanimation=swordslashreversalanim;
+ }
+ if(targetanimation==knifeslashstartanim&&findDistancefast(&victim->coords,&coords)<2&&(victim->id==0||Random()%4==0)){
+ if(victim->weaponactive!=-1){
+ victim->throwtogglekeydown=1;
+ weapons.owner[victim->weaponids[0]]=-1;
+ weapons.velocity[victim->weaponids[0]]=victim->velocity*.2;
+ if(weapons.velocity[victim->weaponids[0]].x==0)weapons.velocity[victim->weaponids[0]].x=.1;
+ weapons.tipvelocity[victim->weaponids[0]]=weapons.velocity[victim->weaponids[0]];
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[victim->num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+
+ victim->weaponactive=-1;
+ for(int j=0;j<numplayers;j++){
+ player[j].wentforweapon=0;
+ }
+ }
+ targetanimation=knifeslashreversedanim;
+ currentanimation=knifeslashreversedanim;
+ victim->currentanimation=knifeslashreversalanim;
+ victim->targetanimation=knifeslashreversalanim;
+ }
+ if(targetanimation!=knifeslashstartanim&&targetanimation!=staffhitanim&&targetanimation!=staffspinhitanim&&targetanimation!=winduppunchanim&&targetanimation!=wolfslapanim&&targetanimation!=swordslashanim&&targetanimation!=swordslashanim){
+ victim->targettilt2=targettilt2;
+ victim->currentframe=currentframe;
+ victim->targetframe=targetframe;
+ victim->target=target;
+ victim->velocity=0;
+ victim->oldcoords=victim->coords;
+ victim->coords=coords;
+ victim->targetrotation=targetrotation;
+ victim->rotation=targetrotation;
+ victim->victim=this;
+ }
+ if(targetanimation==winduppunchanim){
+ targetanimation=winduppunchblockedanim;
+ victim->targetanimation=blockhighleftanim;
+ victim->targetframe=1;
+ victim->target=.5;
+ victim->victim=this;
+ victim->targetrotation=targetrotation+180;
+ }
+ if(targetanimation==wolfslapanim){
+ targetanimation=winduppunchblockedanim;
+ victim->targetanimation=blockhighleftanim;
+ victim->targetframe=1;
+ victim->target=.5;
+ victim->victim=this;
+ victim->targetrotation=targetrotation+180;
+ }
+ if((targetanimation==swordslashanim||targetanimation==staffhitanim||targetanimation==staffspinhitanim)&&victim->weaponactive!=-1){
+ targetanimation=swordslashparriedanim;
+ parriedrecently=.4;
+ victim->parriedrecently=0;
+ victim->targetanimation=swordslashparryanim;
+ victim->targetframe=1;
+ victim->target=.5;
+ victim->victim=this;
+ victim->targetrotation=targetrotation+180;
+
+ if(abs(Random()%20)==0||weapons.type[victim->weaponids[victim->weaponactive]]==knife){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(victim->weaponactive!=-1){
+ if(weapons.type[victim->weaponids[0]]==staff||weapons.type[weaponids[0]]==staff){
+ if(weapons.type[victim->weaponids[0]]==staff)weapons.damage[victim->weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+ if(weapons.type[weaponids[0]]==staff)weapons.damage[weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+
+ PlaySoundEx( swordstaffsound, samp[swordstaffsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[swordstaffsound], gLoc, vel);
+ FSOUND_SetVolume(channels[swordstaffsound], 512);
+ FSOUND_SetPaused(channels[swordstaffsound], FALSE);
+ }
+ else{
+ PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);
+ }
+ }
+ XYZ aim;
+ victim->Puff(righthand);
+ victim->target=0;
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhighanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ weapons.owner[victim->weaponids[0]]=-1;
+ aim=DoRotation(facing,0,90,0)*21;
+ aim.y+=7;
+ weapons.velocity[victim->weaponids[0]]=aim*-.2;
+ weapons.tipvelocity[victim->weaponids[0]]=aim;
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.hitsomething[victim->weaponids[0]]=0;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+ victim->weaponactive=-1;
+ for(int i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+
+
+
+
+
+ /*PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);*/
+ }
+
+ if(abs(Random()%20)==0){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(weaponactive!=-1){
+ if(weapons.type[victim->weaponids[0]]==staff||weapons.type[weaponids[0]]==staff){
+ if(weapons.type[victim->weaponids[0]]==staff)weapons.damage[victim->weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+ if(weapons.type[weaponids[0]]==staff)weapons.damage[weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+
+ PlaySoundEx( swordstaffsound, samp[swordstaffsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[swordstaffsound], gLoc, vel);
+ FSOUND_SetVolume(channels[swordstaffsound], 512);
+ FSOUND_SetPaused(channels[swordstaffsound], FALSE);
+ }
+ else{
+ PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);
+ }
+ }
+
+ XYZ aim;
+ Puff(righthand);
+ target=0;
+ targetframe=0;
+ targetanimation=staggerbackhighanim;
+ targetrotation=targetrotation+180;
+ target=0;
+ weapons.owner[weaponids[0]]=-1;
+ aim=DoRotation(facing,0,90,0)*21;
+ aim.y+=7;
+ weapons.velocity[weaponids[0]]=aim*-.2;
+ weapons.tipvelocity[weaponids[0]]=aim;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.missed[weaponids[0]]=1;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=1;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ if(weaponstuck==num_weapons)weaponstuck=0;
+ }
+ weaponactive=-1;
+ for(int i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+
+
+ /*PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);*/
+ }
+ }
+ if(hasvictim)
+ if(targetanimation==knifeslashstartanim||targetanimation==swordslashanim||targetanimation==staffhitanim||targetanimation==staffspinhitanim){
+ if((targetanimation!=staffhitanim&&targetanimation!=staffspinhitanim)||findDistancefast(&coords,&victim->coords)>.2){
+ //victim->targetanimation=sweepanim;
+ victim->targetanimation=dodgebackanim;
+ victim->targetframe=0;
+ victim->target=0;
+ //victim->velocity=0;
+
+ XYZ rotatetarget;
+ rotatetarget=coords-victim->coords;
+ Normalise(&rotatetarget);
+ victim->targetrotation=-asin(0-rotatetarget.x);
+ victim->targetrotation*=360/6.28;
+ if(rotatetarget.z<0)victim->targetrotation=180-victim->targetrotation;
+
+ victim->targettilt2=-asin(rotatetarget.y)*360/6.28;//*-70;
+
+ victim->lastattack3=victim->lastattack2;
+ victim->lastattack2=victim->lastattack;
+ victim->lastattack=victim->targetanimation;
+ }
+ else
+ {
+ victim->targetanimation=sweepanim;
+ victim->targetframe=0;
+ victim->target=0;
+
+ XYZ rotatetarget;
+ rotatetarget=coords-victim->coords;
+ Normalise(&rotatetarget);
+ victim->targetrotation=-asin(0-rotatetarget.x);
+ victim->targetrotation*=360/6.28;
+ if(rotatetarget.z<0)victim->targetrotation=180-victim->targetrotation;
+
+ victim->targettilt2=-asin(rotatetarget.y)*360/6.28;//*-70;
+
+ victim->lastattack3=victim->lastattack2;
+ victim->lastattack2=victim->lastattack;
+ victim->lastattack=victim->targetanimation;
+ }
+ }
+
+ velocity=0;
+ victim->velocity=0;
+
+ if(aitype!=playercontrolled)feint=0;
+ if(aitype!=playercontrolled&&Random()%3==0&&escapednum<2&&difficulty==2)feint=1;
+ if(aitype!=playercontrolled&&Random()%5==0&&escapednum<2&&difficulty==1)feint=1;
+ if(aitype!=playercontrolled&&Random()%10==0&&escapednum<2&&difficulty==0)feint=1;
+
+ if(victim->id==0&&animation[victim->targetanimation].attack==reversal)numreversals++;
+ }
+}
+
+void Person::DoDamage(float howmuch){
+ if(tutoriallevel!=1)damage+=howmuch/power;
+ if(id!=0)damagedealt+=howmuch/power;
+ if(id==0)damagetaken+=howmuch/power;
+
+ if(id==0&&(bonus==solidhit||bonus==twoxcombo||bonus==threexcombo||bonus==fourxcombo||bonus==megacombo))bonus=0;
+ if(tutoriallevel!=1)permanentdamage+=howmuch/2/power;
+ if(tutoriallevel!=1)superpermanentdamage+=howmuch/4/power;
+ if(permanentdamage>damagetolerance/2&&permanentdamage-howmuch<damagetolerance/2&&Random()%2)DoBlood(1,255);
+ if((permanentdamage>damagetolerance*.8&&Random()%2&&!deathbleeding)||spurt)DoBlood(1,255);
+ spurt=0;
+ if(id==0)camerashake+=howmuch/100;
+ if(id==0&&((howmuch>50&&damage>damagetolerance/2)))blackout=damage/damagetolerance;
+ if(blackout>1)blackout=1;
+
+ if(aitype==passivetype&&damage<damagetolerance&&((tutoriallevel!=1||cananger)&&hostile))aitype=attacktypecutoff;
+ if(tutoriallevel!=1&&aitype!=playercontrolled&&damage<damagetolerance&&damage>damagetolerance*2/3&&creature==rabbittype){
+ if(abs(Random()%2)==0){aitype=gethelptype;
+ lastseentime=12;
+ }
+ else aitype=attacktypecutoff;
+ ally=0;
+ }
+
+ if(howmuch>damagetolerance*50&&skeleton.free!=2){
+ XYZ flatvelocity2;
+ XYZ flatfacing2;
+ for(int i=0;i<skeleton.num_joints; i++){
+ if(!skeleton.free)flatvelocity2=velocity;
+ if(skeleton.free)flatvelocity2=skeleton.joints[i].velocity;
+ if(!skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(skeleton.joints[i].position,0,0,tilt),tilt2,0,0),0,rotation,0)*scale+coords;
+ if(skeleton.free)flatfacing2=skeleton.joints[i].position*scale+coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ sprites.MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
+ sprites.MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .4, 1);
+ sprites.MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
+ }
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( splattersound, samp[splattersound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[splattersound], gLoc, vel);
+ FSOUND_SetVolume(channels[splattersound], 256);
+ FSOUND_SetPaused(channels[splattersound], FALSE);
+
+ skeleton.free=2;
+ DoDamage(10000);
+ RagDoll(0);
+ /*if(autoslomo){
+ slomo=1;
+ slomodelay=.2;
+ }*/
+ if(!dead&&creature==wolftype){
+ bonus=Wolfbonus;
+ bonustime=0;
+ bonusvalue=300;
+ }
+ dead=2;
+ coords=20;
+ }
+
+ if(tutoriallevel!=1||id==0)
+ if(speechdelay<=0&&!dead&&aitype!=playercontrolled){
+ int whichsound=-1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(creature==wolftype){
+ int i=abs(Random()%2);
+ if(i==0)whichsound=snarlsound;
+ if(i==1)whichsound=snarl2sound;
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ if(creature==rabbittype){
+ int i=abs(Random()%2);
+ if(i==0)whichsound=rabbitpainsound;
+ if(i==1&&damage>damagetolerance)whichsound=rabbitpain1sound;
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ //if(i==2)whichsound=rabbitpain2sound;
+ }
+
+ if(whichsound!=-1){
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 512);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+ speechdelay=.3;
+
+ //if(permanentdamage>=damagetolerance&&howmuch<50)permanentdamage=damagetolerance-1;
+ //if(damage>=damagetolerance&&howmuch<30&&!dead)damage=damagetolerance-1;
+}
+
+void Person::DoHead(){
+ static XYZ rotatearound;
+ static XYZ facing;
+ static float lookspeed=500;
+
+ if(!freeze&&!winfreeze&&(!mainmenu||!gamestarted)){
+
+ //head facing
+ targetheadrotation=(float)((int)((0-rotation-targetheadrotation+180)*100)%36000)/100;
+ targetheadrotation2=(float)((int)(targetheadrotation2*100)%36000)/100;
+
+ while(targetheadrotation>180)targetheadrotation-=360;
+ while(targetheadrotation<-180)targetheadrotation+=360;
+
+ if(targetheadrotation>160)targetheadrotation2=targetheadrotation2*-1;
+ if(targetheadrotation<-160)targetheadrotation2=targetheadrotation2*-1;
+ if(targetheadrotation>160)targetheadrotation=targetheadrotation-180;
+ if(targetheadrotation<-160)targetheadrotation=targetheadrotation+180;
+
+ if(targetheadrotation2>120)targetheadrotation2=120;
+ if(targetheadrotation2<-120)targetheadrotation2=-120;
+ if(targetheadrotation>120)targetheadrotation=120;
+ if(targetheadrotation<-120)targetheadrotation=-120;
+
+ if(!isIdle())targetheadrotation2=0;
+ if(isIdle()){
+ if(targetheadrotation>80)targetheadrotation=80;
+ if(targetheadrotation<-80)targetheadrotation=-80;
+ if(targetheadrotation2>50)targetheadrotation2=50;
+ if(targetheadrotation2<-50)targetheadrotation2=-50;
+ }
+
+ if(abs(headrotation-targetheadrotation)<multiplier*lookspeed)headrotation=targetheadrotation;
+ else if(headrotation>targetheadrotation){
+ headrotation-=multiplier*lookspeed;
+ }
+ else if(headrotation<targetheadrotation){
+ headrotation+=multiplier*lookspeed;
+ }
+
+ if(abs(headrotation2-targetheadrotation2)<multiplier*lookspeed/2)headrotation2=targetheadrotation2;
+ else if(headrotation2>targetheadrotation2){
+ headrotation2-=multiplier*lookspeed/2;
+ }
+ else if(headrotation2<targetheadrotation2){
+ headrotation2+=multiplier*lookspeed/2;
+ }
+
+ rotatearound=skeleton.joints[skeleton.jointlabels[neck]].position;
+ skeleton.joints[skeleton.jointlabels[head]].position=rotatearound+DoRotation(skeleton.joints[skeleton.jointlabels[head]].position-rotatearound,headrotation2,0,0);
+
+ facing=0;
+ facing.z=-1;
+ if(targetanimation!=bounceidleanim&&targetanimation!=fightidleanim&&targetanimation!=wolfidle&&targetanimation!=knifefightidleanim&&targetanimation!=drawrightanim&&targetanimation!=drawleftanim&&targetanimation!=walkanim){
+ facing=DoRotation(facing,headrotation2*.4,0,0);
+ facing=DoRotation(facing,0,headrotation*.4,0);
+ }
+
+ if(targetanimation==bounceidleanim||targetanimation==fightidleanim||targetanimation==wolfidle||targetanimation==knifefightidleanim||targetanimation==drawrightanim||targetanimation==drawleftanim){
+ facing=DoRotation(facing,headrotation2*.8,0,0);
+ facing=DoRotation(facing,0,headrotation*.8,0);
+ }
+
+ if(targetanimation==walkanim){
+ facing=DoRotation(facing,headrotation2*.6,0,0);
+ facing=DoRotation(facing,0,headrotation*.6,0);
+ }
+
+ skeleton.specialforward[0]=facing;
+ //skeleton.specialforward[0]=DoRotation(facing,0,rotation,0);
+ static int i;
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible&&(skeleton.muscles[i].parent1->label==head||skeleton.muscles[i].parent2->label==head))
+ {
+ skeleton.FindRotationMuscle(i,targetanimation);
+ }
+ }
+ }
+}
+
+void Person::RagDoll(bool checkcollision){
+ static XYZ change;
+ static int l,i,j;
+ static float speed;
+ if(!skeleton.free){
+ if(id==0)numfalls++;
+ if(id==0&&isFlip())numflipfail++;
+
+ escapednum=0;
+
+ facing=0;
+ facing.z=1;
+ facing=DoRotation(facing,0,rotation,0);
+
+ skeleton.freetime=0;
+
+ skeleton.longdead=0;
+
+ skeleton.free=1;
+ skeleton.broken=0;
+ skeleton.spinny=1;
+ freefall=1;
+ skeleton.freefall=1;
+
+ if(!isnormal(velocity.x))velocity.x=0;
+ if(!isnormal(velocity.y))velocity.y=0;
+ if(!isnormal(velocity.z))velocity.z=0;
+ if(!isnormal(rotation))rotation=0;
+ if(!isnormal(coords.x))coords=0;
+ if(!isnormal(tilt))tilt=0;
+ if(!isnormal(tilt2))tilt2=0;
+
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].delay=0;
+ skeleton.joints[i].locked=0;
+ skeleton.joints[i].position=DoRotation(DoRotation(DoRotation(skeleton.joints[i].position,0,0,tilt),tilt2,0,0),0,rotation,0);
+ if(!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position=DoRotation(skeleton.joints[i].position,0,rotation,0);
+ if(!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position=skeleton.joints[i].position;
+ if(!isnormal(skeleton.joints[i].position.x))skeleton.joints[i].position=coords;
+ skeleton.joints[i].position.y+=.1;
+ skeleton.joints[i].oldposition=skeleton.joints[i].position;
+ skeleton.joints[i].realoldposition=skeleton.joints[i].position*scale+coords;
+ }
+
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].velocity=0;
+ skeleton.joints[i].velchange=0;
+ }
+ skeleton.DoConstraints(&coords,&scale);
+ if(animation[currentanimation].height==lowheight||animation[targetanimation].height==lowheight)
+ {
+ skeleton.DoConstraints(&coords,&scale);
+ skeleton.DoConstraints(&coords,&scale);
+ skeleton.DoConstraints(&coords,&scale);
+ skeleton.DoConstraints(&coords,&scale);
+ }
+
+ speed=animation[targetanimation].speed[targetframe]*2;
+ if(animation[currentanimation].speed[currentframe]>animation[targetanimation].speed[targetframe]){
+ speed=animation[currentanimation].speed[currentframe]*2;
+ }
+ if(transspeed)speed=transspeed*2;
+
+ speed*=speedmult;
+
+ for(i=0;i<skeleton.num_joints;i++){
+ if((animation[currentanimation].attack!=reversed||currentanimation==swordslashreversedanim)&¤tanimation!=rabbitkickanim&&!isLanding()&&!wasLanding()&&animation[currentanimation].height==animation[targetanimation].height)skeleton.joints[i].velocity=velocity/scale+facing*5+DoRotation(DoRotation(DoRotation((animation[targetanimation].position[i][targetframe]-animation[currentanimation].position[i][currentframe])*speed,0,0,tilt),tilt2,0,0),0,rotation,0);
+ else skeleton.joints[i].velocity=velocity/scale+facing*5;
+ change.x=(float)(Random()%100)/100;
+ change.y=(float)(Random()%100)/100;
+ change.z=(float)(Random()%100)/100;
+ skeleton.joints[i].velocity+=change;
+ skeleton.joints[abs(Random()%skeleton.num_joints)].velocity-=change;
+
+ change.x=(float)(Random()%100)/100;
+ change.y=(float)(Random()%100)/100;
+ change.z=(float)(Random()%100)/100;
+ skeleton.joints[i].velchange+=change;
+ skeleton.joints[abs(Random()%skeleton.num_joints)].velchange-=change;
+ }
+
+ if(checkcollision){
+ XYZ average;
+ XYZ lowpoint;
+ XYZ colpoint;
+ int howmany;
+ average=0;
+ howmany=0;
+ for(j=0;j<skeleton.num_joints;j++){
+ average+=skeleton.joints[j].position;
+ howmany++;
+ }
+ average/=howmany;
+ coords+=average*scale;
+ for(j=0;j<skeleton.num_joints;j++){
+ skeleton.joints[j].position-=average;
+ }
+
+ whichpatchx=coords.x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=coords.z/(terrain.size/subdivision*terrain.scale*terraindetail);
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz])
+ for(l=0;l<terrain.patchobjectnum[whichpatchx][whichpatchz];l++){
+ i=terrain.patchobjects[whichpatchx][whichpatchz][l];
+ lowpoint=coords;
+ lowpoint.y+=1;
+ if(SphereCheck(&lowpoint, 3, &colpoint, &objects.position[i], &objects.rotation[i], &objects.model[i])!=-1){
+ coords.x=lowpoint.x;
+ coords.z=lowpoint.z;
+ }
+ }
+ }
+
+ rotation=0;
+ updatedelay=0;
+
+ velocity=0;
+ for(i=0;i<skeleton.num_joints;i++){
+ velocity+=skeleton.joints[i].velocity*scale;
+ }
+ velocity/=skeleton.num_joints;
+
+ if(Random()%2==0){
+ if(weaponactive!=-1&&targetanimation!=rabbitkickanim&&num_weapons>0){
+ weapons.owner[weaponids[0]]=-1;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.velocity[weaponids[0]]=skeleton.joints[skeleton.jointlabels[righthand]].velocity*scale*-.3;
+ weapons.velocity[weaponids[0]].x+=.01;
+ weapons.tipvelocity[weaponids[0]]=skeleton.joints[skeleton.jointlabels[righthand]].velocity*scale;
+ weapons.missed[weaponids[0]]=1;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=1;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ if(weaponstuck==num_weapons)weaponstuck=0;
+ }
+ weaponactive=-1;
+ for(i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+ }
+ }
+
+ targetanimation=bounceidleanim;
+ currentanimation=bounceidleanim;
+ targetframe=0;
+ currentframe=0;
+ }
+}
+
+
+
+void Person::FootLand(int which, float opacity){
+ static XYZ terrainlight;
+ static XYZ footvel,footpoint;
+ if(opacity>=1||skiddelay<=0)
+ if(opacity>1)
+ {
+ footvel=0;
+ if(which==0)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ if(which==1)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ //footpoint.y=coords.y;
+ if(findDistancefast(&footpoint,&viewer))sprites.MakeSprite(cloudsprite, footpoint,footvel, 1,1,1, .5, .2*opacity);
+ }
+ else if(environment==snowyenvironment&&onterrain&&terrain.getOpacity(coords.x,coords.z)<.2){
+ footvel=velocity/5;
+ if(footvel.y<.8)footvel.y=.8;
+ if(which==0)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ if(which==1)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ footpoint.y=terrain.getHeight(footpoint.x,footpoint.z);
+ terrainlight=terrain.getLighting(footpoint.x,footpoint.z);
+ if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, footpoint,footvel*.6, terrainlight.x,terrainlight.y,terrainlight.z, .5, .7*opacity);
+ if(opacity>=1||detail==2)if(detail==2)if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)terrain.MakeDecal(footprintdecal,footpoint,.2,1*opacity,rotation);
+ }
+ else if(environment==grassyenvironment&&onterrain&&terrain.getOpacity(coords.x,coords.z)<.2){
+ footvel=velocity/5;
+ if(footvel.y<.8)footvel.y=.8;
+ if(which==0)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ if(which==1)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ footpoint.y=terrain.getHeight(footpoint.x,footpoint.z);
+ terrainlight=terrain.getLighting(footpoint.x,footpoint.z);
+ if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, footpoint,footvel*.6, terrainlight.x*90/255,terrainlight.y*70/255,terrainlight.z*8/255, .5, .5*opacity);
+ }
+ else if(environment==desertenvironment&&onterrain&&terrain.getOpacity(coords.x,coords.z)<.2){
+ footvel=velocity/5;
+ if(footvel.y<.8)footvel.y=.8;
+ if(which==0)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ if(which==1)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ footpoint.y=terrain.getHeight(footpoint.x,footpoint.z);
+ terrainlight=terrain.getLighting(footpoint.x,footpoint.z);
+ if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, footpoint,footvel*.6, terrainlight.x*190/255,terrainlight.y*170/255,terrainlight.z*108/255, .5, .7*opacity);
+ if(opacity>=1||detail==2)if(detail==2)if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)terrain.MakeDecal(footprintdecal,footpoint,.2,.25*opacity,rotation);
+ }
+ else if(isLanding()||targetanimation==jumpupanim||isLandhard())
+ {
+ footvel=velocity/5;
+ if(footvel.y<.8)footvel.y=.8;
+ if(which==0)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ if(which==1)footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ //footpoint.y=coords.y;
+ if(findDistancefast(&footpoint,&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, footpoint,footvel*.6, 1,1,1, .5, .2*opacity);
+ }
+}
+
+void Person::Puff(int whichlabel){
+ static XYZ footvel,footpoint;
+
+ footvel=0;
+ footpoint=DoRotation(skeleton.joints[skeleton.jointlabels[whichlabel]].position,0,rotation,0)*scale+coords;
+ sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,1,1, .9, .3);
+}
+
+
+/*
+HitStruct Person::BulletCollideWithPlayer(XYZ start, XYZ end){
+float damage=20;
+XYZ tempbulletloc[2];
+XYZ collisionpoint;
+XYZ sparkpos;
+GLfloat M[16];
+int collide;
+float howfar;
+XYZ average;
+XYZ facing;
+int howmany;
+float distancemax;
+HitStruct hitstruct;
+hitstruct.collision=0;
+//Make bounding sphere
+average=0;
+howmany=0;
+for(int j=0;j<skeleton.num_joints;j++){
+average.x=average.x+skeleton.joints[j].position.x;
+average.y=average.y+skeleton.joints[j].position.y;
+average.z=average.z+skeleton.joints[j].position.z;
+howmany++;
+}
+average=average/howmany;
+distancemax=0;
+for(int j=0;j<skeleton.num_joints;j++){
+if(findDistancefast(average,skeleton.joints[j].position)>distancemax){
+distancemax=findDistancefast(average,skeleton.joints[j].position);
+}
+}
+distancemax=fast_sqrt(distancemax);
+//Collide with player
+if(skeleton.free<1){
+start=start-coords;
+end=end-coords;
+if(rotation)start=DoRotation(start,0,-rotation,0);
+if(rotation)end=DoRotation(end,0,-rotation,0);
+}
+tempbulletloc[0]=start;
+tempbulletloc[1]=end;
+if(sphere_line_intersection(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z,
+tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z,
+average.x, average.y, average.z, distancemax)){
+for(int j=0;j<skeleton.num_joints;j++){
+if(skeleton.joints[j].hasparent&&skeleton.joints[j].visible){
+tempbulletloc[0]=start;
+tempbulletloc[1]=end;
+glPushMatrix();
+glLoadIdentity();
+glScalef(1,1/skeleton.joints[j].length,1);
+glRotatef(skeleton.joints[j].rotate2-90,0,0,1);
+glRotatef(skeleton.joints[j].rotate1-90,0,1,0);
+glTranslatef( (-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2),
+(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
+(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
+glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+tempbulletloc[0].x=M[12];
+tempbulletloc[0].y=M[13];
+tempbulletloc[0].z=M[14];
+glPopMatrix();
+glPushMatrix();
+glLoadIdentity();
+glScalef(1,1/skeleton.joints[j].length,1);
+glRotatef(skeleton.joints[j].rotate2-90,0,0,1);
+glRotatef(skeleton.joints[j].rotate1-90,0,1,0);
+glTranslatef( (-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2),
+(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
+(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
+glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+tempbulletloc[1].x=M[12];
+tempbulletloc[1].y=M[13];
+tempbulletloc[1].z=M[14];
+glPopMatrix();
+collide=skeletonmodels[skeleton.joints[j].modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
+if(collide!=-1)
+{
+glPushMatrix();
+glLoadIdentity();
+glTranslatef( (skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2,
+(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2,
+(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2);
+glRotatef(-skeleton.joints[j].rotate1+90,0,1,0);
+glRotatef(-skeleton.joints[j].rotate2+90,0,0,1);
+glScalef(1,skeleton.joints[j].length,1);
+glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+collisionpoint.x=M[12];
+collisionpoint.y=M[13];
+collisionpoint.z=M[14];
+glPopMatrix();
+hitstruct.collision=1;
+hitstruct.hitlocation=collisionpoint;
+hitstruct.joint1=&skeleton.joints[j];
+hitstruct.joint2=skeleton.joints[j].parent;
+}
+}
+}
+for(int j=0;j<skeleton.num_muscles;j++){
+if(skeleton.muscles[j].visible){
+tempbulletloc[0]=start;
+tempbulletloc[1]=end;
+glPushMatrix();
+glLoadIdentity();
+glScalef(1,1/skeleton.muscles[j].length,1);
+glRotatef(skeleton.muscles[j].rotate3,0,1,0);
+glRotatef(skeleton.muscles[j].rotate2-90,0,0,1);
+glRotatef(skeleton.muscles[j].rotate1-90,0,1,0);
+glTranslatef( (-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2),
+(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
+(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
+
+glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+tempbulletloc[0].x=M[12];
+tempbulletloc[0].y=M[13];
+tempbulletloc[0].z=M[14];
+glPopMatrix();
+glPushMatrix();
+glLoadIdentity();
+glScalef(1,1/skeleton.muscles[j].length,1);
+glRotatef(skeleton.muscles[j].rotate3,0,1,0);
+glRotatef(skeleton.muscles[j].rotate2-90,0,0,1);
+glRotatef(skeleton.muscles[j].rotate1-90,0,1,0);
+
+glTranslatef( (-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2),
+(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
+(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
+glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+tempbulletloc[1].x=M[12];
+tempbulletloc[1].y=M[13];
+tempbulletloc[1].z=M[14];
+glPopMatrix();
+collide=skeletonmodels[skeleton.muscles[j].parent1->modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
+if(collide!=-1)
+{
+glPushMatrix();
+glLoadIdentity();
+glTranslatef( (skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2,
+(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2,
+(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2);
+glRotatef(-skeleton.muscles[j].rotate1+90,0,1,0);
+glRotatef(-skeleton.muscles[j].rotate2+90,0,0,1);
+glRotatef(-skeleton.muscles[j].rotate3,0,1,0);
+glScalef(1,findDistance(skeleton.muscles[j].parent1->position,skeleton.muscles[j].parent2->position),1);
+glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
+glGetFloatv(GL_MODELVIEW_MATRIX,M);
+collisionpoint.x=M[12];
+collisionpoint.y=M[13];
+collisionpoint.z=M[14];
+glPopMatrix();
+hitstruct.collision=1;
+hitstruct.hitlocation=collisionpoint;
+hitstruct.joint1=skeleton.muscles[j].parent1;
+hitstruct.joint2=skeleton.muscles[j].parent2;
+}
+}
+}
+}
+if(skeleton.free<1){
+if(rotation)hitstruct.hitlocation=DoRotation(hitstruct.hitlocation,0,rotation,0);
+hitstruct.hitlocation=hitstruct.hitlocation+coords;
+}
+return hitstruct;
+}
+*/
+void Person::DoAnimations(){
+ if(!skeleton.free){
+ int i = 0;
+ static float oldtarget;
+
+ if(isIdle()&¤tanimation!=getIdle())normalsupdatedelay=0;
+
+ if(targetanimation==tempanim||currentanimation==tempanim){
+ animation[tempanim]=tempanimation;
+ }
+ if(targetanimation==jumpupanim||targetanimation==jumpdownanim||isFlip()){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(id==0){
+ FSOUND_3D_SetAttributes(channels[whooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshsound], 64*findLength(&velocity)/5);
+ }
+ if(((velocity.y<-15)||(crouchkeydown&&velocity.y<-8))&&abs(velocity.y)*4>fast_sqrt(velocity.x*velocity.x*velocity.z*velocity.z))landhard=1;
+ if(!crouchkeydown&&velocity.y>=-15)landhard=0;
+ }
+ if((currentanimation==jumpupanim||targetanimation==jumpdownanim)/*&&velocity.y<40*/&&!isFlip()&&(!isLanding()&&!isLandhard())&&((crouchkeydown&&!crouchtogglekeydown))){
+ XYZ targfacing;
+ targfacing=0;
+ targfacing.z=1;
+
+ targfacing=DoRotation(targfacing,0,targetrotation,0);
+
+ if(normaldotproduct(targfacing,velocity)>=-.3)targetanimation=flipanim;
+ else targetanimation=backflipanim;
+ crouchtogglekeydown=1;
+ targetframe=0;
+ target=0;
+
+ if(id==0)numflipped++;
+ }
+
+ if(animation[targetanimation].attack!=reversed)feint=0;
+ if(!crouchkeydown||(isLanding()||isLandhard())||(wasLanding()||wasLandhard())){
+ crouchtogglekeydown=0;
+ if(aitype==playercontrolled)feint=0;
+ }
+ else
+ {
+ if(!crouchtogglekeydown&&animation[targetanimation].attack==reversed&&aitype==playercontrolled&&(escapednum<2||reversaltrain))feint=1;
+ if(!isFlip())crouchtogglekeydown=1;
+ }
+
+
+ if(animation[targetanimation].attack||currentanimation==getupfrombackanim||currentanimation==getupfromfrontanim){
+ if(detail)normalsupdatedelay=0;
+ }
+
+ if(target>=1){
+ if(targetanimation==rollanim&&targetframe==3&&onfire){
+ onfire=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fireendsound, samp[fireendsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fireendsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fireendsound], 256);
+ FSOUND_SetPaused(channels[fireendsound], FALSE);
+ FSOUND_SetPaused(channels[stream_firesound], TRUE);
+ deathbleeding=0;
+ }
+
+ if(targetanimation==rabbittacklinganim&&targetframe==1){
+ //if(victim->aitype==attacktypecutoff&&Random()%2==0&&victim->stunned<=0&&animation[victim->targetanimation].attack==neutral&&victim->id!=0)Reverse();
+ if(victim->aitype==attacktypecutoff&&victim->stunned<=0&&victim->surprised<=0&&victim->id!=0)Reverse();
+ if(targetanimation==rabbittacklinganim&&targetframe==1&&!victim->isCrouch()&&victim->targetanimation!=backhandspringanim){
+ if(normaldotproduct(victim->facing,facing)>0)victim->targetanimation=rabbittackledbackanim;
+ else victim->targetanimation=rabbittackledfrontanim;
+ victim->targetframe=2;
+ victim->target=0;
+ victim->rotation=rotation;
+ victim->targetrotation=rotation;
+ if(victim->aitype==gethelptype)victim->DoDamage(victim->damagetolerance-victim->damage);
+ //victim->DoDamage(30);
+ if(creature==wolftype){
+ DoBloodBig(0,255);
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(1/victim->armorhead,210);
+ }
+ if(id==0){
+ bonus=TackleBonus;
+ bonustime=0;
+ bonusvalue=5;
+ if(victim->aitype==gethelptype)bonusvalue=50;
+ }
+ }
+ }
+
+ if(!drawtogglekeydown&&drawkeydown&&(weaponactive==-1||num_weapons==1)&&(animation[targetanimation].label[targetframe]||(targetanimation!=currentanimation&¤tanimation==rollanim))&&num_weapons>0&&creature!=wolftype){
+ if(weapons.type[weaponids[0]]==knife){
+ if(weaponactive==-1)weaponactive=0;
+ else if(weaponactive==0)weaponactive=-1;
+
+ if(weaponactive==-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+ }
+ if(weaponactive!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+ }
+ drawtogglekeydown=1;
+ }
+ //Footstep sounds
+ if(tutoriallevel!=1||id==0)
+ if((animation[targetanimation].label[targetframe]&&(animation[targetanimation].label[targetframe]<5||animation[targetanimation].label[targetframe]==8))/*||(targetanimation==rollanim&&targetframe==animation[rollanim].numframes-1)*/){
+ int whichsound;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(onterrain){
+ if(terrain.getOpacity(coords.x,coords.z)<.2){
+ if(animation[targetanimation].label[targetframe]==1)whichsound=footstepsound;
+ else whichsound=footstepsound2;
+ if(animation[targetanimation].label[targetframe]==1)FootLand(0,1);
+ if(animation[targetanimation].label[targetframe]==2)FootLand(1,1);
+ if(animation[targetanimation].label[targetframe]==3&&isRun()){
+ FootLand(1,1);
+ FootLand(0,1);
+ }
+
+ }
+ if(terrain.getOpacity(coords.x,coords.z)>=.2){
+ if(animation[targetanimation].label[targetframe]==1)whichsound=footstepsound3;
+ else whichsound=footstepsound4;
+ }
+ }
+ if(!onterrain){
+ if(animation[targetanimation].label[targetframe]==1)whichsound=footstepsound3;
+ else whichsound=footstepsound4;
+ }
+ if(animation[targetanimation].label[targetframe]==4&&(weaponactive==-1||(targetanimation!=knifeslashstartanim&&targetanimation!=knifethrowanim&&targetanimation!=crouchstabanim&&targetanimation!=swordgroundstabanim&&targetanimation!=knifefollowanim))){
+ if(animation[targetanimation].attack!=neutral){
+ i=abs(Random()%3);
+ if(i==0)whichsound=lowwhooshsound;
+ if(i==1)whichsound=midwhooshsound;
+ if(i==2)whichsound=highwhooshsound;
+ }
+ if(animation[targetanimation].attack==neutral)whichsound=movewhooshsound;
+ }
+ else if(animation[targetanimation].label[targetframe]==4)whichsound=knifeswishsound;
+ if(animation[targetanimation].label[targetframe]==8&&tutoriallevel!=1)whichsound=landsound2;
+
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(whichsound!=knifeswishsound)FSOUND_SetVolume(channels[whichsound], 128);
+ if(whichsound!=knifeswishsound&&(targetanimation==staffhitanim||targetanimation==staffgroundsmashanim||targetanimation==staffspinhitanim))FSOUND_SetVolume(channels[whichsound], 256);
+ if(whichsound==knifeswishsound)FSOUND_SetVolume(channels[whichsound], 512);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+
+ if(id==0)
+ if(whichsound==footstepsound||whichsound==footstepsound2||whichsound==footstepsound3||whichsound==footstepsound4){
+ envsound[numenvsounds]=coords;
+ if(targetanimation==wolfrunninganim||targetanimation==rabbitrunninganim)envsoundvol[numenvsounds]=15;
+ else envsoundvol[numenvsounds]=6;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ if(animation[targetanimation].label[targetframe]==3){
+ whichsound--;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 128);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+ //Combat sounds
+ if(tutoriallevel!=1||id==0)
+ if(speechdelay<=0)
+ if(targetanimation!=crouchstabanim&&targetanimation!=swordgroundstabanim&&targetanimation!=staffgroundsmashanim)
+ if((animation[targetanimation].label[targetframe]&&(animation[targetanimation].label[targetframe]<5||animation[targetanimation].label[targetframe]==8))/*||(targetanimation==rollanim&&targetframe==animation[rollanim].numframes-1)*/){
+ int whichsound=-1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(animation[targetanimation].label[targetframe]==4&&aitype!=playercontrolled){
+ if(animation[targetanimation].attack!=neutral){
+ i=abs(Random()%4);
+ if(creature==rabbittype){
+ if(i==0)whichsound=rabbitattacksound;
+ if(i==1)whichsound=rabbitattack2sound;
+ if(i==2)whichsound=rabbitattack3sound;
+ if(i==3)whichsound=rabbitattack4sound;
+ }
+ if(creature==wolftype){
+ if(i==0)whichsound=barksound;
+ if(i==1)whichsound=bark2sound;
+ if(i==2)whichsound=bark3sound;
+ if(i==3)whichsound=barkgrowlsound;
+ }
+ speechdelay=.3;
+ }
+ //if(animation[targetanimation].attack==neutral)whichsound=movewhooshsound;
+ }
+ //else if(animation[targetanimation].label[targetframe]==4)whichsound=knifeswishsound;
+ //if(animation[targetanimation].label[targetframe]==8)whichsound=landsound2;
+
+ if(whichsound!=-1){
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 512);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+
+
+ if((!wasLanding()&&!wasLandhard())&¤tanimation!=getIdle()&&(isLanding()||isLandhard())){
+ FootLand(0,1);
+ FootLand(1,1);
+ }
+
+ transspeed=0;
+ currentoffset=targetoffset;
+ targetframe=currentframe;
+ currentanimation=targetanimation;
+ targetframe++;
+
+ if(targetanimation==removeknifeanim&&animation[targetanimation].label[currentframe]==5){
+ for(i=0;i<weapons.numweapons;i++){
+ if(/*weapons.velocity[i].x==0&&weapons.velocity[i].y==0&&weapons.velocity[i].z==0&&*/weapons.owner[i]==-1)
+ if(findDistancefastflat(&coords,&weapons.position[i])<4&&weaponactive==-1){
+ if(findDistancefast(&coords,&weapons.position[i])>=1){
+ if(weapons.type[i]!=staff){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+
+ weaponactive=0;
+ weapons.owner[i]=id;
+ if(num_weapons>0){
+ weaponids[num_weapons]=weaponids[0];
+ }
+ num_weapons++;
+ weaponids[0]=i;
+ }
+ }
+ }
+ }
+
+ static bool willwork;
+ if(targetanimation==crouchremoveknifeanim&&animation[targetanimation].label[currentframe]==5){
+ for(i=0;i<weapons.numweapons;i++){
+ bool willwork=1;
+ if(weapons.owner[i]!=-1)
+ if(player[weapons.owner[i]].weaponstuck!=-1)
+ if(player[weapons.owner[i]].weaponids[player[weapons.owner[i]].weaponstuck]==i)
+ if(player[weapons.owner[i]].num_weapons>1)willwork=0;
+ if((/*weapons.velocity[i].x==0&&weapons.velocity[i].y==0&&weapons.velocity[i].z==0&&*/weapons.owner[i]==-1)||(hasvictim&&weapons.owner[i]==victim->id&&victim->skeleton.free))
+ if(willwork&&findDistancefastflat(&coords,&weapons.position[i])<3&&weaponactive==-1){
+ if(findDistancefast(&coords,&weapons.position[i])<1||hasvictim){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ bool fleshstuck=0;
+ if(weapons.owner[i]!=-1)
+ if(victim->weaponstuck!=-1){
+ if(victim->weaponids[victim->weaponstuck]==i){
+ fleshstuck=1;
+ }
+ }
+ if(!fleshstuck){
+ if(weapons.type[i]!=staff){
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+ }
+ if(fleshstuck){
+ PlaySoundEx( fleshstabremovesound, samp[fleshstabremovesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabremovesound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabremovesound], 128);
+ FSOUND_SetPaused(channels[fleshstabremovesound], FALSE);
+ }
+ weaponactive=0;
+ if(weapons.owner[i]!=-1){
+
+ victim=&player[weapons.owner[i]];
+ if(victim->num_weapons==1)victim->num_weapons=0;
+ else victim->num_weapons=1;
+
+ //victim->weaponactive=-1;
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+
+ for(int j=0;j<victim->skeleton.num_joints;j++){
+ victim->skeleton.joints[j].velchange=0;
+ victim->skeleton.joints[j].locked=0;
+ }
+
+ XYZ relative;
+ relative=0;
+ relative.y=10;
+ Normalise(&relative);
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.position[i];
+ if(victim->weaponstuck!=-1){
+ if(victim->weaponids[victim->weaponstuck]==i){
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .8, .3);
+ weapons.bloody[i]=2;
+ weapons.blooddrip[i]=5;
+ victim->weaponstuck=-1;
+ }
+ }
+ if(victim->num_weapons>0){
+ if(victim->weaponstuck!=0&&victim->weaponstuck!=-1)victim->weaponstuck=0;
+ if(victim->weaponids[0]==i)
+ victim->weaponids[0]=victim->weaponids[victim->num_weapons];
+ }
+
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*6;
+ victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity+=relative*6;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity+=relative*6;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity+=relative*6;
+ }
+ weapons.owner[i]=id;
+ if(num_weapons>0){
+ weaponids[num_weapons]=weaponids[0];
+ }
+ num_weapons++;
+ weaponids[0]=i;
+ }
+ }
+ }
+ }
+
+ if(currentanimation==drawleftanim&&animation[targetanimation].label[currentframe]==5){
+ if(weaponactive==-1)weaponactive=0;
+ else if(weaponactive==0){
+ weaponactive=-1;
+ if(num_weapons==2){
+ int buffer;
+ buffer=weaponids[0];
+ weaponids[0]=weaponids[1];
+ weaponids[1]=buffer;
+ }
+ }
+ if(weaponactive==-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+ }
+ if(weaponactive!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+ }
+
+
+ if((currentanimation==walljumprightkickanim&&targetanimation==walljumprightkickanim)||(currentanimation==walljumpleftkickanim&&targetanimation==walljumpleftkickanim)){
+ XYZ rotatetarget=DoRotation(skeleton.forward,0,rotation,0);
+ Normalise(&rotatetarget);
+ targetrotation=-asin(0-rotatetarget.x);
+ targetrotation*=360/6.28;
+ if(rotatetarget.z<0)targetrotation=180-targetrotation;
+
+ if(targetanimation==walljumprightkickanim)targetrotation+=40;
+ if(targetanimation==walljumpleftkickanim)targetrotation-=40;
+ }
+
+ bool dojumpattack;
+ dojumpattack=0;
+ if((targetanimation==rabbitrunninganim||targetanimation==wolfrunninganim)&&targetframe==3&&(jumpkeydown||attackkeydown||id!=0))dojumpattack=1;
+ if(hasvictim)
+ if(findDistancefast(&victim->coords,&/*player[i].*/coords)<5&&victim->aitype==gethelptype&&(attackkeydown)&&!victim->skeleton.free&&victim->isRun()&&victim->runninghowlong>=1)dojumpattack=1; if(!hostile)dojumpattack=0;
+ if(dojumpattack){
+ if((targetanimation==rabbitrunninganim||targetanimation==wolfrunninganim)&&id==0){
+ targetanimation=rabbittackleanim;
+ targetframe=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( jumpsound, samp[jumpsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[jumpsound], gLoc, vel);
+ FSOUND_SetVolume(channels[jumpsound], 128);
+ FSOUND_SetPaused(channels[jumpsound], FALSE);
+ }
+
+ float closestdist;
+ closestdist=0;
+ int closestid;
+ closestid=-1;
+ XYZ targetloc;
+ targetloc=velocity;
+ Normalise(&targetloc);
+ targetloc+=coords;
+ for(i=0;i<numplayers;i++){
+ if(i!=id)
+ if(findDistancefast(&targetloc,&player[i].coords)<closestdist||closestdist==0){
+ closestdist=findDistancefast(&targetloc,&player[i].coords);
+ closestid=i;
+ }
+ }
+ if(closestid!=-1)
+ if(closestdist<5&&!player[closestid].dead&&animation[player[closestid].targetanimation].height!=lowheight&&player[closestid].targetanimation!=backhandspringanim){
+ hasvictim=1;
+ victim=&player[closestid];
+ coords=victim->coords;
+ currentanimation=rabbittacklinganim;
+ targetanimation=rabbittacklinganim;
+ currentframe=0;
+ targetframe=1;
+ XYZ rotatetarget;
+ if(coords.z!=victim->coords.z||coords.x!=victim->coords.x){
+ rotatetarget=coords-victim->coords;
+ Normalise(&rotatetarget);
+ targetrotation=-asin(0-rotatetarget.x);
+ targetrotation*=360/6.28;
+ if(rotatetarget.z<0)targetrotation=180-targetrotation;
+ }
+ if(targetanimation!=rabbitrunninganim){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( jumpsound, samp[jumpsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[jumpsound], gLoc, vel);
+ FSOUND_SetVolume(channels[jumpsound], 128);
+ FSOUND_SetPaused(channels[jumpsound], FALSE);
+ }
+ }
+ }
+
+ //Move impacts
+ float damagemult=1*power;
+ if(creature==wolftype)damagemult=2.5*power;
+ if(hasvictim){damagemult/=victim->damagetolerance/200;}
+ //if(onfire)damagemult=3;
+ if((animation[targetanimation].attack==normalattack||targetanimation==walljumprightkickanim||targetanimation==walljumpleftkickanim)&&(!feint)&&(victim->skeleton.free!=2||targetanimation==killanim||targetanimation==dropkickanim||targetanimation==crouchstabanim||targetanimation==swordgroundstabanim||targetanimation==staffgroundsmashanim)){
+ if(targetanimation==spinkickanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&3&&animation[victim->targetanimation].height!=lowheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2||creature==wolftype){
+ victim->spurt=1;
+ DoBlood(.2,250);
+ if(creature==wolftype)DoBloodBig(0,250);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhead,175);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*100/victim->protectionhead);
+
+ if(id==0){
+ SolidHitBonus();
+ }
+ }
+ }
+
+ if(targetanimation==wolfslapanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&3&&animation[victim->targetanimation].height!=lowheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2||creature==wolftype){
+ victim->spurt=1;
+ if(creature==wolftype)DoBloodBig(0,235);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( whooshhitsound, samp[whooshhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshhitsound], 512);
+ FSOUND_SetPaused(channels[whooshhitsound], FALSE);
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2,175);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative.y-=1;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*20;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*100;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*50/victim->protectionhead);
+ }
+ }
+
+ if(targetanimation==walljumprightkickanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&animation[victim->targetanimation].height!=lowheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ victim->spurt=1;
+ DoBlood(.2,250);
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 160);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhead,175);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=facing;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*150/victim->protectionhead);
+
+ if(victim->damage>victim->damagetolerance){
+ if(id==0){
+ bonus=style;
+ bonustime=0;
+ bonusvalue=150;
+ }
+ }
+ else if(id==0){
+ SolidHitBonus();
+ }
+ }
+ }
+
+ if(targetanimation==walljumpleftkickanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&animation[victim->targetanimation].height!=lowheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ victim->spurt=1;
+ DoBlood(.2,250);
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 160);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhead,175);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=facing;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*150/victim->protectionhead);
+
+ if(victim->damage>victim->damagetolerance){
+ if(id==0){
+ bonus=style;
+ bonustime=0;
+ bonusvalue=150;
+ }
+ }
+ else if(id==0){
+ SolidHitBonus();
+ }
+ }
+ }
+
+ if(targetanimation==blockhighleftstrikeanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&animation[victim->targetanimation].height!=lowheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,235);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( whooshhitsound, samp[whooshhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshhitsound], 512);
+ FSOUND_SetPaused(channels[whooshhitsound], FALSE);
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*30;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*100;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*50/victim->protectionhead);
+ }
+ }
+
+ if(targetanimation==killanim&&animation[targetanimation].label[currentframe]==8){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&victim->dead){
+ escapednum=0;
+ if(id==0)camerashake+=.2;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ /*PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ */
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 128);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+ victim->skeleton.spinny=1;
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velchange=0;
+ victim->skeleton.joints[i].delay=0;
+ victim->skeleton.joints[i].locked=0;
+ //victim->skeleton.joints[i].velocity=0;
+ }
+
+ XYZ relative;
+ relative=0;
+ relative.y=1;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity.y=relative.y*10;
+ victim->skeleton.joints[i].position.y+=relative.y*.3;
+ victim->skeleton.joints[i].oldposition.y+=relative.y*.3;
+ victim->skeleton.joints[i].realoldposition.y+=relative.y*.3;
+ }
+ victim->Puff(abdomen);
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity.y=relative.y*400;
+ }
+ }
+
+ if(targetanimation==killanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*9&&victim->dead){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*90;
+ }
+ victim->Puff(abdomen);
+ if(victim->dead!=2&&victim->permanentdamage>victim->damagetolerance-250&&autoslomo){
+ slomo=1;
+ slomodelay=.2;
+ }
+ victim->DoDamage(damagemult*500/victim->protectionhigh);
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*300;
+ }
+ }
+
+ if(targetanimation==dropkickanim&&animation[targetanimation].label[currentframe]==7){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*9&&victim->skeleton.free){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( thudsound, samp[thudsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[thudsound], gLoc, vel);
+ FSOUND_SetVolume(channels[thudsound], 400);
+ FSOUND_SetPaused(channels[thudsound], FALSE);
+ }
+
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+ victim->skeleton.spinny=1;
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velchange=0;
+ //victim->skeleton.joints[i].delay=0;
+ victim->skeleton.joints[i].locked=0;
+ }
+ XYZ relative;
+ relative=victim->coords-coords;
+ Normalise(&relative);
+ relative.y+=.3;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*20;
+ }
+ if(id==0&&!victim->dead){
+ SolidHitBonus();
+ }
+
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*20/victim->protectionhigh);
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ staggerdelay=.5;
+ if(!victim->dead)staggerdelay=1.2;
+
+
+ }
+ }
+
+ if((targetanimation==crouchstabanim||targetanimation==swordgroundstabanim)&&animation[targetanimation].label[currentframe]==5){
+ // if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*9){
+ //if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(hasvictim)
+ if(!victim->skeleton.free)hasvictim=0;
+
+ if(!hasvictim){
+ terrain.MakeDecal(blooddecalfast,(weapons.tippoint[weaponids[weaponactive]]*.8+weapons.position[weaponids[weaponactive]]*.2),.08,.6,Random()%360);
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+ }
+
+ if(victim&&hasvictim){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3){
+
+ XYZ where,startpoint,endpoint,movepoint,colpoint;
+ float rotationpoint;
+ int whichtri;
+ if(weapons.type[weaponids[weaponactive]]==knife){
+ where=(weapons.tippoint[weaponids[weaponactive]]*.6+weapons.position[weaponids[weaponactive]]*.4);
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ //where=scale;
+ startpoint=where;
+ startpoint.y+=100;
+ endpoint=where;
+ endpoint.y-=100;
+ }
+ if(weapons.type[weaponids[weaponactive]]==sword){
+ where=weapons.position[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ startpoint=where;
+ where=weapons.tippoint[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ endpoint=where;
+ }
+ if(weapons.type[weaponids[weaponactive]]==staff){
+ where=weapons.position[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ startpoint=where;
+ where=weapons.tippoint[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ endpoint=where;
+ }
+ movepoint=0;
+ rotationpoint=0;
+ whichtri=victim->skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &colpoint, &movepoint, &rotationpoint);
+
+ if(whichtri!=-1){
+ if(victim->dead!=2){
+ victim->DoDamage(abs((victim->damagetolerance-victim->permanentdamage)*2));
+ if(id==0&&!victim->dead){
+ bonus=FinishedBonus;
+ bonustime=0;
+ bonusvalue=200;
+ }
+ }
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velchange=0;
+ victim->skeleton.joints[i].locked=0;
+ //victim->skeleton.joints[i].velocity=0;
+ }
+ PlaySoundEx( fleshstabsound, samp[fleshstabsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabsound], 128);
+ FSOUND_SetPaused(channels[fleshstabsound], FALSE);
+
+ }
+ if(whichtri!=-1||weapons.bloody[weaponids[weaponactive]]){
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+ weapons.blooddripdelay[weaponids[weaponactive]]=0;
+ }
+ if(whichtri==-1){
+ hasvictim=0;
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+ }
+ }
+ }
+ }
+
+ if((targetanimation==crouchstabanim||targetanimation==swordgroundstabanim)&&animation[targetanimation].label[currentframe]==6){
+ // if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*9){
+ //if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(!hasvictim){
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+
+ if(victim&&hasvictim){
+ XYZ footvel,footpoint;
+
+ PlaySoundEx( fleshstabremovesound, samp[fleshstabremovesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabremovesound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabremovesound], 128);
+ FSOUND_SetPaused(channels[fleshstabremovesound], FALSE);
+
+ footvel=0;
+ footpoint=(weapons.tippoint[weaponids[weaponactive]]*.8+weapons.position[weaponids[weaponactive]]*.2);
+
+ if(weapons.type[weaponids[weaponactive]]==sword){
+ XYZ where,startpoint,endpoint,movepoint;
+ float rotationpoint;
+ int whichtri;
+
+ where=weapons.position[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ startpoint=where;
+ where=weapons.tippoint[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ endpoint=where;
+
+ movepoint=0;
+ rotationpoint=0;
+ whichtri=victim->skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
+ footpoint+=victim->coords;
+
+ if(whichtri==-1){
+ footpoint=(weapons.tippoint[weaponids[weaponactive]]*.8+weapons.position[weaponids[weaponactive]]*.2);
+ }
+ }
+ if(weapons.type[weaponids[weaponactive]]==staff){
+ XYZ where,startpoint,endpoint,movepoint;
+ float rotationpoint;
+ int whichtri;
+
+ where=weapons.position[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ startpoint=where;
+ where=weapons.tippoint[weaponids[weaponactive]];
+ where-=victim->coords;
+ if(!victim->skeleton.free)where=DoRotation(where,0,-victim->rotation,0);
+ endpoint=where;
+
+ movepoint=0;
+ rotationpoint=0;
+ whichtri=victim->skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
+ footpoint+=victim->coords;
+
+ if(whichtri==-1){
+ footpoint=(weapons.tippoint[weaponids[weaponactive]]*.8+weapons.position[weaponids[weaponactive]]*.2);
+ }
+ }
+ hasvictim=victim->DoBloodBigWhere(2,220,footpoint);
+ if(hasvictim){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3){
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velchange=0;
+ victim->skeleton.joints[i].locked=0;
+ //victim->skeleton.joints[i].velocity=0;
+ }
+
+ XYZ relative;
+ relative=0;
+ relative.y=10;
+ Normalise(&relative);
+ //victim->Puff(abdomen);
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .8, .3);
+
+ if(victim->bloodloss<victim->damagetolerance){
+ victim->bloodloss+=1000;
+ victim->bled=0;
+ }
+
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*20;
+ }
+ }
+ }
+ if(!hasvictim&&onterrain){
+ weapons.bloody[weaponids[weaponactive]]=0;
+ weapons.blooddrip[weaponids[weaponactive]]=0;
+ }
+ }
+
+ if(targetanimation==upunchanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,235);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ //if(!victim->isIdle()||victim->damage>victim->damagetolerance-60){
+ if(1==1){
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ }
+ else {
+ if(tutoriallevel!=1){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 256);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ }
+
+ //if(!victim->isIdle()||victim->damage>victim->damagetolerance-60)
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=relative*30;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*150;
+
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhardanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ victim->stunned=1;
+
+ victim->Puff(head);
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*60/victim->protectionhigh);
+
+ if(id==0){
+ SolidHitBonus();
+ }
+ }
+ }
+
+
+ if(targetanimation==winduppunchanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*2){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ //if(!victim->isIdle()||victim->damage>victim->damagetolerance-60){
+ if(victim->damage<=victim->damagetolerance-60&&normaldotproduct(victim->facing,victim->coords-coords)<(scale*5)*(scale*5)*0&&animation[victim->targetanimation].height!=lowheight){
+ if(tutoriallevel!=1){
+ PlaySoundEx( thudsound, samp[thudsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[thudsound], gLoc, vel);
+ FSOUND_SetVolume(channels[thudsound], 512);
+ FSOUND_SetPaused(channels[thudsound], FALSE);
+ }
+ }
+ else if(victim->damage<=victim->damagetolerance-60&&normaldotproduct(victim->facing,victim->coords-coords)<(scale*5)*(scale*5)*0&&animation[victim->targetanimation].height==lowheight){
+ if(tutoriallevel!=1){
+ PlaySoundEx( whooshhitsound, samp[whooshhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshhitsound], 512);
+ FSOUND_SetPaused(channels[whooshhitsound], FALSE);
+ }
+ }
+ else {
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 256);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ }
+
+ if(victim->damage>victim->damagetolerance-60||normaldotproduct(victim->facing,victim->coords-coords)>0||animation[victim->targetanimation].height==lowheight)
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative.y=.3;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=relative*5;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*400;
+
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhardanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ victim->stunned=1;
+
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*60/victim->protectionhigh);
+
+ if(id==0){
+ SolidHitBonus();
+ }
+ }
+ }
+
+ if(targetanimation==blockhighleftanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*4){
+ if(victim->id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 256);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+
+ Puff(righthand);
+ }
+ }
+
+ if(targetanimation==swordslashparryanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*4){
+ if(victim->id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(weaponactive!=-1){
+ if(weapons.type[victim->weaponids[0]]==staff||weapons.type[weaponids[0]]==staff){
+ if(weapons.type[victim->weaponids[0]]==staff)weapons.damage[victim->weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+ if(weapons.type[weaponids[0]]==staff)weapons.damage[weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+
+ PlaySoundEx( swordstaffsound, samp[swordstaffsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[swordstaffsound], gLoc, vel);
+ FSOUND_SetVolume(channels[swordstaffsound], 512);
+ FSOUND_SetPaused(channels[swordstaffsound], FALSE);
+ }
+ else{
+ PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);
+ }
+ }
+
+ //Puff(righthand);
+ }
+ }
+
+ if(targetanimation==knifethrowanim&&animation[targetanimation].label[currentframe]==5){
+ if(weaponactive!=-1){
+ escapednum=0;
+ XYZ aim;
+ weapons.owner[weaponids[0]]=-1;
+ aim=victim->coords+DoRotation(victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position,0,victim->rotation,0)*victim->scale+victim->velocity*findDistance(&victim->coords,&coords)/50-(coords+DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,rotation,0)*scale);
+ Normalise(&aim);
+ /*if(victim->targetanimation==jumpupanim||victim->targetanimation==jumpdownanim){
+ aim=DoRotation(aim,(float)abs(Random()%15)-7,(float)abs(Random()%15)-7,0);
+ }*/
+ weapons.velocity[weaponids[0]]=aim*50;
+ weapons.tipvelocity[weaponids[0]]=aim*50;
+ weapons.missed[weaponids[0]]=0;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=0;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ }
+ weaponactive=-1;
+ }
+ }
+
+ if(targetanimation==knifeslashstartanim&&animation[targetanimation].label[currentframe]==5){
+ if(hasvictim)
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*4.5&&/*animation[victim->targetanimation].height!=lowheight&&*/victim->targetanimation!=dodgebackanim&&victim->targetanimation!=rollanim){
+ escapednum=0;
+ //if(Random()%2){
+ if(tutoriallevel!=1)victim->DoBloodBig(1.5/victim->armorhigh,225);
+ //}
+
+ if(id==0){
+ bonus=Slicebonus;
+ bonustime=0;
+ bonusvalue=10;
+ }
+ if(tutoriallevel!=1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( knifeslicesound, samp[knifeslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifeslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifeslicesound], 512);
+ FSOUND_SetPaused(channels[knifeslicesound], FALSE);
+ }
+ //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ if(animation[victim->targetanimation].attack&&(victim->aitype!=playercontrolled||victim->targetanimation==knifeslashstartanim)&&(victim->creature==rabbittype||victim->deathbleeding<=0)){
+ if(victim->id != 0 || difficulty==2){
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhardanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ }
+ }
+ victim->lowreversaldelay=0;
+ victim->highreversaldelay=0;
+ if(aitype!=playercontrolled)weaponmissdelay=.6;
+
+ if(tutoriallevel!=1)if(bloodtoggle&&!weapons.bloody[weaponids[weaponactive]])weapons.bloody[weaponids[weaponactive]]=1;
+ if(tutoriallevel!=1)weapons.blooddrip[weaponids[weaponactive]]+=3;
+
+ XYZ footvel,footpoint;
+ footvel=0;
+ if(skeleton.free){
+ footpoint=(victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position+victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position)/2*victim->scale+victim->coords;
+ }
+ if(!skeleton.free){
+ footpoint=DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position+victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position)/2,0,victim->rotation,0)*victim->scale+victim->coords;
+ }
+ if(tutoriallevel!=1){
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .6, .3);
+ footvel=DoRotation(facing,0,90,0)*.8;
+ //footvel.y-=.3;
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .2, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .2, 1);
+ }
+ if(tutoriallevel==1){
+ sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,1,1, .6, .3);
+ }
+ victim->DoDamage(damagemult*0);
+ }
+ }
+ if(targetanimation==swordslashanim&&animation[targetanimation].label[currentframe]==5&&victim->targetanimation!=rollanim){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*6.5&&victim->targetanimation!=dodgebackanim){
+ if(victim->weaponactive==-1||normaldotproduct(victim->facing,victim->coords-coords)>0||(Random()%2==0)){
+ if(id==0){
+ bonus=Slashbonus;
+ bonustime=0;
+ bonusvalue=40;
+ }
+ escapednum=0;
+ if(tutoriallevel!=1){
+ if(normaldotproduct(victim->facing,victim->coords-coords)<0)victim->DoBloodBig(2/victim->armorhigh,190);
+ else victim->DoBloodBig(2/victim->armorhigh,185);
+ victim->deathbleeding=1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( swordslicesound, samp[swordslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[swordslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[swordslicesound], 512);
+ FSOUND_SetPaused(channels[swordslicesound], FALSE);
+ }
+ //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ //if(animation[victim->targetanimation].attack){
+ //if(victim->creature==rabbittype){
+ if(tutoriallevel!=1){
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhardanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ }
+ //}
+ //}
+
+ if(tutoriallevel!=1){
+ if(bloodtoggle&&!weapons.bloody[weaponids[weaponactive]])weapons.bloody[weaponids[weaponactive]]=1;
+ weapons.blooddrip[weaponids[weaponactive]]+=3;
+
+ float bloodlossamount;
+ bloodlossamount=200+abs((float)(Random()%40))-20;
+ victim->bloodloss+=bloodlossamount/victim->armorhigh;
+ //victim->bloodloss+=100*(6.5-findDistancefast(&coords,&victim->coords));
+ victim->DoDamage(damagemult*0);
+
+ XYZ footvel,footpoint;
+ footvel=0;
+ if(skeleton.free){
+ footpoint=(victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position+victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position)/2*victim->scale+victim->coords;
+ }
+ if(!skeleton.free){
+ footpoint=DoRotation((victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].position+victim->skeleton.joints[victim->skeleton.jointlabels[neck]].position)/2,0,victim->rotation,0)*victim->scale+victim->coords;
+ }
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=DoRotation(facing,0,90,0)*.8;
+ footvel.y-=.3;
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .3, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .3, 1);
+ }
+ }
+ else {
+
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(victim->weaponactive!=-1){
+ if(weapons.type[victim->weaponids[0]]==staff||weapons.type[weaponids[0]]==staff){
+ if(weapons.type[victim->weaponids[0]]==staff)weapons.damage[victim->weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+ if(weapons.type[weaponids[0]]==staff)weapons.damage[weaponids[0]]+=.2+float(abs(Random()%100)-50)/250;
+
+ PlaySoundEx( swordstaffsound, samp[swordstaffsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[swordstaffsound], gLoc, vel);
+ FSOUND_SetVolume(channels[swordstaffsound], 512);
+ FSOUND_SetPaused(channels[swordstaffsound], FALSE);
+ }
+ else{
+ PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);
+ }
+ }
+
+
+ XYZ aim;
+ victim->Puff(righthand);
+ victim->target=0;
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhighanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ weapons.owner[victim->weaponids[0]]=-1;
+ aim=DoRotation(facing,0,90,0)*21;
+ aim.y+=7;
+ weapons.velocity[victim->weaponids[0]]=aim*-.2;
+ weapons.tipvelocity[victim->weaponids[0]]=aim;
+ weapons.missed[victim->weaponids[0]]=1;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.freetime[victim->weaponids[0]]=0;
+ weapons.firstfree[victim->weaponids[0]]=1;
+ weapons.physics[victim->weaponids[0]]=1;
+ victim->num_weapons--;
+ if(victim->num_weapons){
+ victim->weaponids[0]=victim->weaponids[num_weapons];
+ if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+ victim->weaponactive=-1;
+ for(i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+
+ /*PlaySoundEx( metalhitsound, samp[metalhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[metalhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[metalhitsound], 512);
+ FSOUND_SetPaused(channels[metalhitsound], FALSE);*/
+
+ }
+ }
+ }
+
+ if(targetanimation==staffhitanim&&animation[targetanimation].label[currentframe]==5&&victim->targetanimation!=rollanim){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*6.5&&victim->targetanimation!=dodgebackanim&&victim->targetanimation!=sweepanim){
+ if(tutoriallevel!=1){
+ weapons.damage[weaponids[0]]+=.4+float(abs(Random()%100)-50)/250;
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2||creature==wolftype){
+ victim->spurt=1;
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( staffheadsound, samp[staffheadsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[staffheadsound], gLoc, vel);
+ FSOUND_SetVolume(channels[staffheadsound], 256);
+ FSOUND_SetPaused(channels[staffheadsound], FALSE);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);
+ relative.y-=1;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*60;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*230;
+ victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity+=relative*damagemult*230;
+ //FootLand(1,2);
+ victim->Puff(head);
+ if(tutoriallevel!=1){
+ victim->DoDamage(damagemult*120/victim->protectionhigh);
+
+ if(id==0){
+ bonus=solidhit;
+ bonustime=0;
+ bonusvalue=30;
+ }
+ }
+ }
+ }
+
+ if(targetanimation==staffspinhitanim&&animation[targetanimation].label[currentframe]==5&&victim->targetanimation!=rollanim){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*6.5&&victim->targetanimation!=dodgebackanim&&victim->targetanimation!=sweepanim){
+ if(tutoriallevel!=1){
+ weapons.damage[weaponids[0]]+=.6+float(abs(Random()%100)-50)/250;
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2||creature==wolftype){
+ victim->spurt=1;
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( staffheadsound, samp[staffheadsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[staffheadsound], gLoc, vel);
+ FSOUND_SetVolume(channels[staffheadsound], 256);
+ FSOUND_SetPaused(channels[staffheadsound], FALSE);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*220;
+ victim->skeleton.joints[victim->skeleton.jointlabels[neck]].velocity+=relative*damagemult*220;
+ //FootLand(1,2);
+ victim->Puff(head);
+ if(tutoriallevel!=1){victim->DoDamage(damagemult*350/victim->protectionhead);
+
+ if(id==0){
+ bonus=solidhit;
+ bonustime=0;
+ bonusvalue=60;
+ }
+ }
+ }
+ }
+
+ if(targetanimation==staffgroundsmashanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*6.5){
+ escapednum=0;
+ if(tutoriallevel!=1){
+ if(!victim->dead)weapons.damage[weaponids[0]]+=.4+float(abs(Random()%100)-50)/500;
+ if(id==0)camerashake+=.4;
+ if(Random()%2||creature==wolftype){
+ victim->spurt=1;
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( staffbodysound, samp[staffbodysound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[staffbodysound], gLoc, vel);
+ FSOUND_SetVolume(channels[staffbodysound], 256);
+ FSOUND_SetPaused(channels[staffbodysound], FALSE);
+ }
+ victim->skeleton.longdead=0;
+ victim->skeleton.free=1;
+ victim->skeleton.broken=0;
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velchange=0;
+ victim->skeleton.joints[i].locked=0;
+ //victim->skeleton.joints[i].velocity=0;
+ }
+
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=0;
+ /*relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);*/
+ relative.y=-1;
+ Normalise(&relative);
+ if(!victim->dead){
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=relative*damagemult*40;
+ }
+ //FootLand(1,2);
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*40;
+ }
+ if(victim->dead){
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=relative*damagemult*abs(Random()%20);
+ }
+ //FootLand(1,2);
+ //victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*20;
+ }
+ victim->Puff(abdomen);
+ if(tutoriallevel!=1){victim->DoDamage(damagemult*100/victim->protectionhigh);
+
+ if(!victim->dead){
+ if(id==0){
+ bonus=solidhit;
+ bonustime=0;
+ bonusvalue=40;
+ }
+ }
+ }
+ }
+ }
+
+ if(targetanimation==lowkickanim&&animation[targetanimation].label[currentframe]==5){
+ if(findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&animation[victim->targetanimation].height!=highheight){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+
+ if(id==0){
+ SolidHitBonus();
+ }
+
+ if(animation[victim->targetanimation].height==lowheight){
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,250);
+ }
+ victim->RagDoll(0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ victim->Puff(head);
+ victim->DoDamage(damagemult*100/victim->protectionhead);
+ if(victim->howactive==typesleeping)victim->DoDamage(damagemult*150/victim->protectionhead);
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhead,175);
+ }
+ }
+ else{
+ if(victim->damage>=victim->damagetolerance)victim->RagDoll(0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*10;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhighanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ if(tutoriallevel!=1){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*30/victim->protectionhigh);
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhigh,170);
+ }
+ }
+
+ }
+ }
+
+ if(targetanimation==sweepanim&&animation[targetanimation].label[currentframe]==5){
+ if(victim->targetanimation!=jumpupanim&&findDistancefast(&coords,&victim->coords)<(scale*5)*(scale*5)*3&&victim!=this){
+ escapednum=0;
+ if(id==0)camerashake+=.2;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ XYZ relative;
+ relative=victim->coords-coords;
+ relative.y=0;
+ Normalise(&relative);
+
+ if(animation[victim->targetanimation].height==middleheight||animation[victim->currentanimation].height==middleheight||victim->damage>=victim->damagetolerance-40){
+ victim->RagDoll(0);
+
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*15;
+ }
+ relative=DoRotation(relative,0,-90,0);
+ relative.y+=.1;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ if(victim->skeleton.joints[i].label==leftfoot||victim->skeleton.joints[i].label==rightfoot||victim->skeleton.joints[i].label==leftankle||victim->skeleton.joints[i].label==rightankle)
+ victim->skeleton.joints[i].velocity=relative*80;
+ }
+ victim->Puff(rightankle);
+ victim->Puff(leftankle);
+ victim->DoDamage(damagemult*40/victim->protectionlow);
+ }
+ else{
+ if(victim->damage>=victim->damagetolerance)victim->RagDoll(0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*10;
+ }
+ relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ if(victim->skeleton.joints[i].label==leftfoot||victim->skeleton.joints[i].label==rightfoot||victim->skeleton.joints[i].label==leftankle||victim->skeleton.joints[i].label==rightankle)
+ victim->skeleton.joints[i].velocity+=relative*damagemult*80;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ victim->targetframe=0;
+ victim->targetanimation=staggerbackhighanim;
+ victim->targetrotation=targetrotation+180;
+ victim->target=0;
+ if(tutoriallevel!=1){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*30/victim->protectionlow);
+ }
+
+ if(id==0){
+ SolidHitBonus();
+ }
+
+ }
+ }
+ }
+ if(animation[targetanimation].attack==reversal&&(!victim->feint||(victim->lastattack==victim->lastattack2&&victim->lastattack2==victim->lastattack3&&Random()%2)||targetanimation==knifefollowanim)){
+ if(targetanimation==spinkickreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,230);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ if(creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhigh,170);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-oldcoords;
+ relative.y=0;
+ Normalise(&relative);
+ //relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*150/victim->protectionhigh);
+
+ if(id==0){
+ bonus=Reversal;
+ bonustime=0;
+ bonusvalue=60;
+ }
+ }
+
+ if((targetanimation==swordslashreversalanim||targetanimation==knifeslashreversalanim||targetanimation==staffhitreversalanim||targetanimation==staffspinhitreversalanim)&&animation[targetanimation].label[currentframe]==5){
+ if(victim->weaponactive!=-1&&victim->num_weapons>0){
+ if(weapons.owner[victim->weaponids[victim->weaponactive]]==victim->id){
+ weapons.owner[victim->weaponids[victim->weaponactive]]=id;
+ weaponactive=0;
+ if(num_weapons>0){
+ weaponids[num_weapons]=weaponids[victim->weaponactive];
+ }
+ num_weapons++;
+ weaponids[0]=victim->weaponids[victim->weaponactive];
+ victim->num_weapons--;
+ if(victim->num_weapons>0){
+ victim->weaponids[victim->weaponactive]=victim->weaponids[victim->num_weapons];
+ //if(victim->weaponstuck==victim->num_weapons)victim->weaponstuck=0;
+ }
+ victim->weaponactive=-1;
+ }
+ }
+ }
+
+ if(targetanimation==staffhitreversalanim&&animation[targetanimation].label[currentframe]==5){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,230);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( whooshhitsound, samp[whooshhitsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whooshhitsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshhitsound], 128);
+ FSOUND_SetPaused(channels[whooshhitsound], FALSE);
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-oldcoords;
+ relative.y=0;
+ Normalise(&relative);
+ //relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*30;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*70/victim->protectionhigh);
+ }
+
+ if(targetanimation==staffspinhitreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,230);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(id==0){
+ bonus=staffreversebonus;
+ bonustime=0;
+ bonusvalue=100;
+ }
+
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ victim->RagDoll(0);
+ if(id==0){
+ bonus=staffreversebonus;
+ bonustime=0;
+ bonusvalue=100;
+ }
+
+ XYZ relative;
+ relative=victim->coords-oldcoords;
+ relative.y=0;
+ Normalise(&relative);
+ //relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*30;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(head);
+ victim->DoDamage(damagemult*70/victim->protectionhigh);
+ }
+
+ if(targetanimation==upunchreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ victim->RagDoll(1);
+ XYZ relative;
+ relative=facing;
+ relative.y=0;
+ Normalise(&relative);
+ //relative*=-1;
+ relative.y-=.1;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*70;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity*=.1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity*=.2;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity*=.5;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity*=.7;
+ victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity*=.1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity*=.2;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity*=.5;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity*=.7;
+
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*90/victim->protectionhigh);
+
+ if(id==0){
+ bonus=Reversal;
+ bonustime=0;
+ bonusvalue=60;
+ }
+
+ bool doslice;
+ doslice=0;
+ if(weaponactive!=-1||creature==wolftype)doslice=1;
+ if(creature==rabbittype&&weaponactive!=-1)if(weapons.type[weaponids[0]]==staff)doslice=0;
+ if(doslice){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(weaponactive!=-1){
+ victim->DoBloodBig(2/victim->armorhigh,225);
+ PlaySoundEx( knifeslicesound, samp[knifeslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifeslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifeslicesound], 512);
+ FSOUND_SetPaused(channels[knifeslicesound], FALSE);
+ if(bloodtoggle&&!weapons.bloody[weaponids[weaponactive]])weapons.bloody[weaponids[weaponactive]]=1;
+ weapons.blooddrip[weaponids[weaponactive]]+=3;
+ }
+ if(weaponactive==-1&&creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhigh,175);
+ }
+ }
+ }
+
+
+
+ if(targetanimation==swordslashreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ victim->RagDoll(1);
+ XYZ relative;
+ relative=facing;
+ relative.y=0;
+ Normalise(&relative);
+ //relative*=-1;
+ relative.y-=.1;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*70;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[lefthand]].velocity*=.1-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftwrist]].velocity*=.2-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftelbow]].velocity*=.5-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[leftshoulder]].velocity*=.7-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[righthand]].velocity*=.1-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightwrist]].velocity*=.2-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightelbow]].velocity*=.5-1;
+ victim->skeleton.joints[victim->skeleton.jointlabels[rightshoulder]].velocity*=.7-1;
+
+ if(id==0){
+ bonus=swordreversebonus;
+ bonustime=0;
+ bonusvalue=100;
+ }
+ //victim->DoDamage(90);
+
+ /*if(weaponactive!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ victim->DoBloodBig(2,225);
+ PlaySoundEx( knifeslicesound, samp[knifeslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifeslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifeslicesound], 512);
+ FSOUND_SetPaused(channels[knifeslicesound], FALSE);
+ if(bloodtoggle&&!weapons.bloody[weaponids[weaponactive]])weapons.bloody[weaponids[weaponactive]]=1;
+ weapons.blooddrip[weaponids[weaponactive]]+=3;
+ }*/
+ }
+
+ if(hasvictim&&targetanimation==knifeslashreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,230);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ victim->RagDoll(0);
+ XYZ relative;
+ relative=victim->coords-oldcoords;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,-90,0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[abdomen]].velocity+=relative*damagemult*200;
+ //FootLand(1,2);
+ victim->Puff(abdomen);
+ victim->DoDamage(damagemult*30/victim->protectionhigh);
+
+ if(id==0){
+ bonus=Reversal;
+ bonustime=0;
+ bonusvalue=60;
+ }
+ }
+
+ if(hasvictim&&targetanimation==sneakattackanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ victim->RagDoll(0);
+ victim->skeleton.spinny=0;
+ XYZ relative;
+ relative=facing*-1;
+ relative.y=-3;
+ Normalise(&relative);
+ if(victim->id==0)relative/=30;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*40;
+ }
+ //victim->DoDamage(1000);
+ victim->damage=victim->damagetolerance;
+ victim->permanentdamage=victim->damagetolerance-1;
+ bool doslice;
+ doslice=0;
+ if(weaponactive!=-1||creature==wolftype)doslice=1;
+ if(creature==rabbittype&&weaponactive!=-1)if(weapons.type[weaponids[0]]==staff)doslice=0;
+ if(doslice){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(weaponactive!=-1){
+ victim->DoBloodBig(200,225);
+ PlaySoundEx( knifeslicesound, samp[knifeslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifeslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifeslicesound], 512);
+ FSOUND_SetPaused(channels[knifeslicesound], FALSE);
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+ }
+
+ if(creature==wolftype&&weaponactive==-1){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2,175);
+ }
+ }
+ if(id==0){
+ bonus=spinecrusher;
+ bonustime=0;
+ bonusvalue=100;
+ }
+ }
+
+ if(hasvictim&&(targetanimation==knifefollowanim||targetanimation==knifesneakattackanim)&&animation[targetanimation].label[currentframe]==5){
+ if(weaponactive!=-1&&victim->bloodloss<victim->damagetolerance){
+ escapednum=0;
+ if(targetanimation==knifefollowanim)victim->DoBloodBig(200,210);
+ if(targetanimation==knifesneakattackanim){
+ /*victim->DoBloodBig(200,195);
+ XYZ bloodvel;
+ bloodvel=0;
+ bloodvel.z=20;
+ bloodvel.y=5;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ sprites.MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ */
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.tippoint[weaponids[0]];
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=(weapons.tippoint[weaponids[0]]-weapons.position[weaponids[0]]);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .3, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .3, 1);
+ victim->DoBloodBig(200,195);
+ if(id==0){
+ bonus=tracheotomy;
+ bonustime=0;
+ bonusvalue=100;
+ }
+
+ //victim->neckspurtamount=5;
+ }
+ if(targetanimation==knifefollowanim){
+ if(id==0){
+ bonus=Stabbonus;
+ bonustime=0;
+ bonusvalue=40;
+ }
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.tippoint[weaponids[0]];
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=(weapons.tippoint[weaponids[0]]-weapons.position[weaponids[0]])*-1;
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .2, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .2, 1);
+
+ }
+ victim->bloodloss+=10000;
+ victim->velocity=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( fleshstabsound, samp[fleshstabsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabsound], 512);
+ FSOUND_SetPaused(channels[fleshstabsound], FALSE);
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+ }
+ }
+
+ if(hasvictim&&(targetanimation==knifefollowanim||targetanimation==knifesneakattackanim)&&animation[targetanimation].label[currentframe]==6){
+ escapednum=0;
+ victim->velocity=0;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=0;
+ }
+ if(targetanimation==knifefollowanim){
+ victim->RagDoll(0);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=0;
+ }
+ }
+ if(weaponactive!=-1&&animation[victim->targetanimation].attack!=reversal){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( fleshstabremovesound, samp[fleshstabremovesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabremovesound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabremovesound], 512);
+ FSOUND_SetPaused(channels[fleshstabremovesound], FALSE);
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.tippoint[weaponids[0]];
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=(weapons.tippoint[weaponids[0]]-weapons.position[weaponids[0]])*-1;
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .3, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .3, 1);
+ }
+ }
+
+ if(hasvictim&&(targetanimation==swordsneakattackanim)&&animation[targetanimation].label[currentframe]==5){
+ if(weaponactive!=-1&&victim->bloodloss<victim->damagetolerance){
+ if(id==0){
+ bonus=backstab;
+ bonustime=0;
+ bonusvalue=100;
+ }
+
+ escapednum=0;
+
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=(weapons.tippoint[weaponids[0]]+weapons.position[weaponids[0]])/2;
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=(weapons.tippoint[weaponids[0]]-weapons.position[weaponids[0]]);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,DoRotation(footvel*5,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .3, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .3, 1);
+ victim->DoBloodBig(200,180);
+ victim->DoBloodBig(200,215);
+ victim->bloodloss+=10000;
+ victim->velocity=0;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( fleshstabsound, samp[fleshstabsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabsound], 512);
+ FSOUND_SetPaused(channels[fleshstabsound], FALSE);
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+ }
+ }
+
+ if(hasvictim&&targetanimation==swordsneakattackanim&&animation[targetanimation].label[currentframe]==6){
+ escapednum=0;
+ victim->velocity=0;
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity=0;
+ }
+ if(weaponactive!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( fleshstabremovesound, samp[fleshstabremovesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabremovesound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabremovesound], 512);
+ FSOUND_SetPaused(channels[fleshstabremovesound], FALSE);
+ if(bloodtoggle)weapons.bloody[weaponids[weaponactive]]=2;
+ weapons.blooddrip[weaponids[weaponactive]]+=5;
+
+ XYZ footvel,footpoint;
+ footvel=0;
+ footpoint=weapons.tippoint[weaponids[0]];
+ if(bloodtoggle)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .9, .3);
+ footvel=(weapons.tippoint[weaponids[0]]-weapons.position[weaponids[0]])*-1;
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*7,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodsprite,footpoint,DoRotation(footvel*3,(float)(Random()%20),(float)(Random()%20),0), 1,1,1, .05, .9);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*5, 1,1,1, .3, 1);
+ sprites.MakeSprite(bloodflamesprite, footpoint,footvel*2, 1,1,1, .3, 1);
+ }
+ }
+
+ if(targetanimation==sweepreversalanim&&animation[targetanimation].label[currentframe]==7){
+ escapednum=0;
+ if(id==0)camerashake+=.4;
+ if(Random()%2){
+ victim->spurt=1;
+ DoBlood(.2,240);
+ }
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=victim->coords.x;
+ gLoc[1]=victim->coords.y;
+ gLoc[2]=victim->coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(weaponactive==-1){
+ if(tutoriallevel!=1){
+ PlaySoundEx( heavyimpactsound, samp[heavyimpactsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[heavyimpactsound], gLoc, vel);
+ FSOUND_SetVolume(channels[heavyimpactsound], 128);
+ FSOUND_SetPaused(channels[heavyimpactsound], FALSE);
+ }
+ }
+ bool doslice;
+ doslice=0;
+ if(weaponactive!=-1||creature==wolftype)doslice=1;
+ if(creature==rabbittype&&weaponactive!=-1)if(weapons.type[weaponids[0]]==staff)doslice=0;
+ if(doslice){
+ if(weaponactive!=-1){
+ victim->DoBloodBig(2/victim->armorhead,225);
+ PlaySoundEx( knifeslicesound, samp[knifeslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifeslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifeslicesound], 512);
+ FSOUND_SetPaused(channels[knifeslicesound], FALSE);
+ if(bloodtoggle&&!weapons.bloody[weaponids[weaponactive]])weapons.bloody[weaponids[weaponactive]]=1;
+ weapons.blooddrip[weaponids[weaponactive]]+=3;
+ }
+ if(weaponactive==-1&&creature==wolftype){
+ PlaySoundEx( clawslicesound, samp[clawslicesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[clawslicesound], gLoc, vel);
+ FSOUND_SetVolume(channels[clawslicesound], 128);
+ FSOUND_SetPaused(channels[clawslicesound], FALSE);
+ victim->spurt=1;
+ victim->DoBloodBig(2/victim->armorhead,175);
+ }
+ }
+
+ if(id==0){
+ bonus=Reversal;
+ bonustime=0;
+ bonusvalue=60;
+ }
+
+ victim->Puff(neck);
+
+ XYZ relative;
+ //relative=victim->coords-oldcoords;
+ relative=facing*-1;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);
+ relative.y=.5;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*20;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ if(victim->damage<victim->damagetolerance-100)victim->velocity=relative*200;
+ victim->DoDamage(damagemult*100/victim->protectionhead);
+ victim->velocity=0;
+ }
+
+ if(targetanimation==sweepreversalanim&&((animation[targetanimation].label[currentframe]==9&&victim->damage<victim->damagetolerance)||(animation[targetanimation].label[currentframe]==7&&victim->damage>victim->damagetolerance))){
+ escapednum=0;
+ victim->RagDoll(0);
+ XYZ relative;
+ //relative=victim->coords-oldcoords;
+ relative=facing*-1;
+ relative.y=0;
+ Normalise(&relative);
+ relative=DoRotation(relative,0,90,0);
+ relative.y=.5;
+ Normalise(&relative);
+ for(i=0;i<victim->skeleton.num_joints;i++){
+ victim->skeleton.joints[i].velocity+=relative*damagemult*20;
+ }
+ victim->skeleton.joints[victim->skeleton.jointlabels[head]].velocity+=relative*damagemult*200;
+ }
+
+ if(hasvictim&&(targetanimation==spinkickreversalanim||targetanimation==sweepreversalanim||targetanimation==rabbitkickreversalanim||targetanimation==upunchreversalanim||targetanimation==jumpreversalanim||targetanimation==swordslashreversalanim||targetanimation==knifeslashreversalanim||targetanimation==rabbittacklereversal||targetanimation==wolftacklereversal||targetanimation==staffhitreversalanim||targetanimation==staffspinhitreversalanim))
+ if(victim->damage>victim->damagetolerance&&bonus!=reverseko){
+ if(id==0){
+ bonus=reverseko;
+ bonustime=0;
+ bonusvalue=100;
+ }
+ }
+ }
+
+
+ //Animation end
+ if(targetframe>animation[currentanimation].numframes-1){
+ targetframe=0;
+ if(wasStop()){
+ targetanimation=getIdle();
+ FootLand(0,1);
+ FootLand(1,1);
+ }
+ if(currentanimation==rabbittackleanim||currentanimation==rabbittacklinganim){
+ targetanimation=rollanim;
+ targetframe=3;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 128);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+ }
+ if(currentanimation==staggerbackhighanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==staggerbackhardanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==removeknifeanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==crouchremoveknifeanim){
+ targetanimation=getCrouch();
+ }
+ if(currentanimation==backhandspringanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==dodgebackanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==drawleftanim){
+ targetanimation=getIdle();
+ }
+ if(currentanimation==drawrightanim||currentanimation==crouchdrawrightanim){
+ targetanimation=getIdle();
+ if(currentanimation==crouchdrawrightanim){
+ targetanimation=getCrouch();
+ }
+ if(weaponactive==-1)weaponactive=0;
+ else if(weaponactive==0){
+ weaponactive=-1;
+ if(num_weapons==2){
+ int buffer;
+ buffer=weaponids[0];
+ weaponids[0]=weaponids[1];
+ weaponids[1]=buffer;
+ }
+ }
+
+ if(weaponactive==-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+ }
+ if(weaponactive!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+ }
+ }
+ if(currentanimation==rollanim){
+ targetanimation=getCrouch();
+ FootLand(0,1);
+ FootLand(1,1);
+ }
+ if(isFlip()){
+ if(targetanimation==walljumprightkickanim){
+ targetrot=-190;
+ }
+ if(targetanimation==walljumpleftkickanim){
+ targetrot=190;
+ }
+ targetanimation=jumpdownanim;
+ }
+ if(currentanimation==climbanim){
+ targetanimation=getCrouch();
+ targetframe=1;
+ coords+=facing*.1;
+ if(!isnormal(coords.x))
+ coords=oldcoords;
+ oldcoords=coords;
+ collided=0;
+ targetoffset=0;
+ currentoffset=0;
+ grabdelay=1;
+ velocity=0;
+ collided=0;
+ avoidcollided=0;
+ }
+ if(targetanimation==rabbitkickreversalanim){
+ targetanimation=getCrouch();
+ lastfeint=0;
+ }
+ if(targetanimation==jumpreversalanim){
+ targetanimation=getCrouch();
+ lastfeint=0;
+ }
+ if(targetanimation==walljumprightanim||targetanimation==walljumpbackanim||targetanimation==walljumpfrontanim){
+ if(attackkeydown&&targetanimation!=walljumpfrontanim){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=0;i<numplayers;i++){
+ if(id!=i&&player[i].coords.y<coords.y&&!player[i].skeleton.free){
+ distance=findDistancefast(&player[i].coords,&coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ }
+ if(closestdist>0&&closest>=0&&closestdist<16){
+ victim=&player[closest];
+ targetanimation=walljumprightkickanim;
+ targetframe=0;
+ XYZ rotatetarget=victim->coords-coords;
+ Normalise(&rotatetarget);
+ rotation=-asin(0-rotatetarget.x);
+ rotation*=360/6.28;
+ if(rotatetarget.z<0)rotation=180-rotation;
+ targettilt2=-asin(rotatetarget.y)*360/6.28;
+ velocity=(victim->coords-coords)*4;
+ velocity.y+=2;
+ transspeed=40;
+ }
+ }
+ if(targetanimation==walljumpbackanim){
+ targetanimation=backflipanim;
+ targetframe=3;
+ velocity=facing*-8;
+ velocity.y=4;
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], FALSE);
+ }
+ if(targetanimation==walljumprightanim){
+ targetanimation=rightflipanim;
+ targetframe=4;
+ targetrotation-=90;
+ rotation-=90;
+ velocity=DoRotation(facing,0,30,0)*-8;
+ velocity.y=4;
+ }
+ if(targetanimation==walljumpfrontanim){
+ targetanimation=frontflipanim;
+ targetframe=2;
+ //targetrotation-=180;
+ ////rotation-=180;
+ velocity=facing*8;
+ velocity.y=4;
+ }
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], FALSE);
+ }
+ if(targetanimation==walljumpleftanim){
+ if(attackkeydown){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(i=0;i<numplayers;i++){
+ if(id!=i&&player[i].coords.y<coords.y&&!player[i].skeleton.free){
+ distance=findDistancefast(&player[i].coords,&coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ }
+ if(closestdist>0&&closest>=0&&closestdist<16){
+ victim=&player[closest];
+ targetanimation=walljumpleftkickanim;
+ targetframe=0;
+ XYZ rotatetarget=victim->coords-coords;
+ Normalise(&rotatetarget);
+ rotation=-asin(0-rotatetarget.x);
+ rotation*=360/6.28;
+ if(rotatetarget.z<0)rotation=180-rotation;
+ targettilt2=-asin(rotatetarget.y)*360/6.28;
+ velocity=(victim->coords-coords)*4;
+ velocity.y+=2;
+ transspeed=40;
+ }
+ }
+ if(targetanimation!=walljumpleftkickanim){
+ targetanimation=leftflipanim;
+ targetframe=4;
+ targetrotation+=90;
+ rotation+=90;
+ velocity=DoRotation(facing,0,-30,0)*-8;
+ velocity.y=4;
+ }
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], FALSE);
+ }
+ if(targetanimation==sneakattackanim){
+ float ycoords=oldcoords.y;
+ currentanimation=getCrouch();
+ targetanimation=getCrouch();
+ targetframe=1;
+ currentframe=0;
+ targetrotation+=180;
+ rotation+=180;
+ targettilt2*=-1;
+ tilt2*=-1;
+ transspeed=1000000;
+ targetheadrotation+=180;
+ coords-=facing*.7;
+ if(onterrain)coords.y=terrain.getHeight(coords.x,coords.z);
+
+ lastfeint=0;
+ }
+ if(targetanimation==knifesneakattackanim||targetanimation==swordsneakattackanim){
+ float ycoords=oldcoords.y;
+ targetanimation=getIdle();
+ targetframe=0;
+ if(onterrain)coords.y=terrain.getHeight(coords.x,coords.z);
+
+ lastfeint=0;
+ }
+ if(currentanimation==knifefollowanim){
+ targetanimation=getIdle();
+ lastfeint=0;
+ }
+ if(animation[targetanimation].attack==reversal&¤tanimation!=sneakattackanim&¤tanimation!=knifesneakattackanim&¤tanimation!=swordsneakattackanim&¤tanimation!=knifefollowanim){
+ float ycoords=oldcoords.y;
+ targetanimation=getStop();
+ targetrotation+=180;
+ rotation+=180;
+ targettilt2*=-1;
+ tilt2*=-1;
+ transspeed=1000000;
+ targetheadrotation+=180;
+ if(!isnormal(coords.x))
+ coords=oldcoords;
+ if(currentanimation==spinkickreversalanim||currentanimation==swordslashreversalanim)
+ oldcoords=coords+facing*.5;
+ else if(currentanimation==sweepreversalanim)
+ oldcoords=coords+facing*1.1;
+ else if(currentanimation==upunchreversalanim){
+ oldcoords=coords+facing*1.5;
+ targetrotation+=180;
+ rotation+=180;
+ targetheadrotation+=180;
+ targettilt2*=-1;
+ tilt2*=-1;
+ }
+ else if(currentanimation==knifeslashreversalanim){
+ oldcoords=coords+facing*.5;
+ targetrotation+=90;
+ rotation+=90;
+ targetheadrotation+=90;
+ targettilt2=0;
+ tilt2=0;
+ }
+ else if(currentanimation==staffspinhitreversalanim){
+ targetrotation+=180;
+ rotation+=180;
+ targetheadrotation+=180;
+ targettilt2=0;
+ tilt2=0;
+ }
+ if(onterrain)oldcoords.y=terrain.getHeight(oldcoords.x,oldcoords.z);
+ else oldcoords.y=ycoords;
+ currentoffset=coords-oldcoords;
+ targetoffset=0;
+ coords=oldcoords;
+
+ lastfeint=0;
+ }
+ if(currentanimation==knifesneakattackedanim||currentanimation==swordsneakattackedanim){
+ velocity=0;
+ velocity.y=-5;
+ RagDoll(0);
+ }
+ if(animation[targetanimation].attack==reversed){
+ escapednum++;
+ if(targetanimation==sweepreversedanim)targetrotation+=90;
+ targetanimation=backhandspringanim;
+ targetframe=2;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( landsound, samp[landsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound], 128);
+ FSOUND_SetPaused(channels[landsound], FALSE);
+
+ if(currentanimation==upunchreversedanim||currentanimation==swordslashreversedanim){
+ targetanimation=rollanim;
+ targetframe=5;
+ oldcoords=coords;
+ coords+=(DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)+DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0))/2*scale;
+ coords.y=oldcoords.y;
+ }
+ if(currentanimation==knifeslashreversedanim){
+ targetanimation=rollanim;
+ targetframe=0;
+ targetrotation+=90;
+ rotation+=90;
+ oldcoords=coords;
+ coords+=(DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)+DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0))/2*scale;
+ coords.y=oldcoords.y;
+ }
+ }
+ if(wasFlip()){
+ targetanimation=jumpdownanim;
+ }
+ if(wasLanding())targetanimation=getIdle();
+ if(wasLandhard())targetanimation=getIdle();
+ if(currentanimation==spinkickanim||currentanimation==getupfrombackanim||currentanimation==getupfromfrontanim||currentanimation==lowkickanim){
+ targetanimation=getIdle();
+ oldcoords=coords;
+ coords+=(DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)+DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0))/2*scale;
+ coords.y=oldcoords.y;
+ //coords+=DoRotation(animation[currentanimation].offset,0,rotation,0)*scale;
+ targetoffset.y=coords.y;
+ if(onterrain)targetoffset.y=terrain.getHeight(coords.x,coords.z);
+ currentoffset=DoRotation(animation[currentanimation].offset*-1,0,rotation,0)*scale;
+ currentoffset.y-=(coords.y-targetoffset.y);
+ coords.y=targetoffset.y;
+ targetoffset=0;
+ normalsupdatedelay=0;
+ }
+ if(currentanimation==upunchanim){
+ targetanimation=getStop();
+ normalsupdatedelay=0;
+ lastfeint=0;
+ }
+ if(currentanimation==rabbitkickanim&&targetanimation!=backflipanim){
+ targetrotation=rotation;
+ bool hasstaff;
+ hasstaff=0;
+ if(num_weapons>0)if(weapons.type[0]==staff)hasstaff=1;
+ if(!hasstaff)DoDamage(35);
+ RagDoll(0);
+ lastfeint=0;
+ rabbitkickragdoll=1;
+ }
+ if(currentanimation==rabbitkickreversedanim){
+ if(!feint){
+ velocity=0;
+ velocity.y=-10;
+ //DoDamage(100);
+ RagDoll(0);
+ skeleton.spinny=0;
+ if(id!=0)SolidHitBonus();
+ }
+ if(feint){
+ escapednum++;
+ targetanimation=rollanim;
+ coords+=facing;
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+ }
+ lastfeint=0;
+ }
+ if(currentanimation==rabbittackledbackanim||currentanimation==rabbittackledfrontanim){
+ velocity=0;
+ velocity.y=-10;
+ RagDoll(0);
+ skeleton.spinny=0;
+ }
+ if(currentanimation==jumpreversedanim){
+ if(!feint){
+ velocity=0;
+ velocity.y=-10;
+ //DoDamage(100);
+ RagDoll(0);
+ skeleton.spinny=0;
+ if(id!=0)SolidHitBonus();
+ }
+ if(feint){
+ escapednum++;
+ targetanimation=rollanim;
+ coords+=facing*2;
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+ }
+ lastfeint=0;
+ }
+
+ if(animation[currentanimation].attack==normalattack&&!victim->skeleton.free&&victim->targetanimation!=staggerbackhighanim&&victim->targetanimation!=staggerbackhardanim&&targetanimation!=winduppunchblockedanim&&targetanimation!=blockhighleftanim&&targetanimation!=swordslashparryanim&&targetanimation!=swordslashparriedanim&&targetanimation!=crouchstabanim&&targetanimation!=swordgroundstabanim){
+ targetanimation=getupfromfrontanim;
+ lastfeint=0;
+ }
+ else if(animation[currentanimation].attack==normalattack){
+ targetanimation=getIdle();
+ lastfeint=0;
+ }
+ if(currentanimation==blockhighleftanim&&aitype!=playercontrolled){
+ targetanimation=blockhighleftstrikeanim;
+ }
+ if(currentanimation==knifeslashstartanim||currentanimation==knifethrowanim||currentanimation==swordslashanim||currentanimation==staffhitanim||currentanimation==staffgroundsmashanim||currentanimation==staffspinhitanim){
+ targetanimation=getIdle();
+ lastfeint=0;
+ }
+ if(currentanimation==spinkickanim&&victim->skeleton.free){
+ if(creature==rabbittype)targetanimation=fightidleanim;
+ }
+ }
+ target=0;
+
+ if(isIdle()&&!wasIdle())normalsupdatedelay=0;
+
+ if(currentanimation==jumpupanim&&velocity.y<0&&!isFlip()){
+ targetanimation=jumpdownanim;
+ }
+ }
+ if(!skeleton.free){
+ oldtarget=target;
+ if(!transspeed&&animation[targetanimation].attack!=2&&animation[targetanimation].attack!=3){
+ if(!isRun()||!wasRun()){
+ if(animation[targetanimation].speed[targetframe]>animation[currentanimation].speed[currentframe])
+ target+=multiplier*animation[targetanimation].speed[targetframe]*speed*2;
+ if(animation[targetanimation].speed[targetframe]<=animation[currentanimation].speed[currentframe])
+ target+=multiplier*animation[currentanimation].speed[currentframe]*speed*2;
+ }
+ if(isRun()&&wasRun()){
+ float tempspeed;
+ tempspeed=velspeed;
+ if(tempspeed<10*speedmult)tempspeed=10*speedmult;
+ target+=multiplier*animation[targetanimation].speed[currentframe]*speed*1.7*tempspeed/(speed*45*scale);
+ }
+ }
+ else if(transspeed)target+=multiplier*transspeed*speed*2;
+ else{
+ if(!isRun()||!wasRun()){
+ if(animation[targetanimation].speed[targetframe]>animation[currentanimation].speed[currentframe])
+ target+=multiplier*animation[targetanimation].speed[targetframe]*2;
+ if(animation[targetanimation].speed[targetframe]<=animation[currentanimation].speed[currentframe])
+ target+=multiplier*animation[currentanimation].speed[currentframe]*2;
+ }
+ }
+
+ if(currentanimation!=targetanimation)target=(target+oldtarget)/2;
+
+ if(target>1){currentframe=targetframe; target=1;}
+ oldrot=rot;
+ rot=targetrot*target;
+ rotation+=rot-oldrot;
+ if(target==1){
+ rot=0;
+ oldrot=0;
+ targetrot=0;
+ }
+ if(currentanimation!=oldcurrentanimation||targetanimation!=oldtargetanimation||((currentframe!=oldcurrentframe||targetframe!=oldtargetframe)&&!calcrot)){
+ //Old rotates
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].position=animation[currentanimation].position[i][currentframe];
+ }
+
+ skeleton.FindForwards();
+
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible)
+ {
+ skeleton.FindRotationMuscle(i,targetanimation);
+ }
+ }
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible)
+ {
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate1*100)%36000)/100))skeleton.muscles[i].oldrotate1=(float)((int)(skeleton.muscles[i].rotate1*100)%36000)/100;
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate2*100)%36000)/100))skeleton.muscles[i].oldrotate2=(float)((int)(skeleton.muscles[i].rotate2*100)%36000)/100;
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate3*100)%36000)/100))skeleton.muscles[i].oldrotate3=(float)((int)(skeleton.muscles[i].rotate3*100)%36000)/100;
+ }
+ }
+
+ //New rotates
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].position=animation[targetanimation].position[i][targetframe];
+ }
+
+ skeleton.FindForwards();
+
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible)
+ {
+ skeleton.FindRotationMuscle(i,targetanimation);
+ }
+ }
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible)
+ {
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate1*100)%36000)/100))skeleton.muscles[i].newrotate1=(float)((int)(skeleton.muscles[i].rotate1*100)%36000)/100;
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate2*100)%36000)/100))skeleton.muscles[i].newrotate2=(float)((int)(skeleton.muscles[i].rotate2*100)%36000)/100;
+ if(isnormal((float)((int)(skeleton.muscles[i].rotate3*100)%36000)/100))skeleton.muscles[i].newrotate3=(float)((int)(skeleton.muscles[i].rotate3*100)%36000)/100;
+ if(skeleton.muscles[i].newrotate3>skeleton.muscles[i].oldrotate3+180)skeleton.muscles[i].newrotate3-=360;
+ if(skeleton.muscles[i].newrotate3<skeleton.muscles[i].oldrotate3-180)skeleton.muscles[i].newrotate3+=360;
+ if(skeleton.muscles[i].newrotate2>skeleton.muscles[i].oldrotate2+180)skeleton.muscles[i].newrotate2-=360;
+ if(skeleton.muscles[i].newrotate2<skeleton.muscles[i].oldrotate2-180)skeleton.muscles[i].newrotate2+=360;
+ if(skeleton.muscles[i].newrotate1>skeleton.muscles[i].oldrotate1+180)skeleton.muscles[i].newrotate1-=360;
+ if(skeleton.muscles[i].newrotate1<skeleton.muscles[i].oldrotate1-180)skeleton.muscles[i].newrotate1+=360;
+ }
+ }
+ }
+ if(currentframe>=animation[currentanimation].numframes)currentframe=animation[currentanimation].numframes-1;
+
+ oldcurrentanimation=currentanimation;
+ oldtargetanimation=targetanimation;
+ oldtargetframe=targetframe;
+ oldcurrentframe=currentframe;
+
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].velocity=(animation[currentanimation].position[i][currentframe]*(1-target)+animation[targetanimation].position[i][targetframe]*(target)-skeleton.joints[i].position)/multiplier;
+ skeleton.joints[i].position=animation[currentanimation].position[i][currentframe]*(1-target)+animation[targetanimation].position[i][targetframe]*(target);
+ }
+ offset=currentoffset*(1-target)+targetoffset*target;
+ for(i=0;i<skeleton.num_muscles;i++){
+ if(skeleton.muscles[i].visible)
+ {
+ skeleton.muscles[i].rotate1=skeleton.muscles[i].oldrotate1*(1-target)+skeleton.muscles[i].newrotate1*(target);
+ skeleton.muscles[i].rotate2=skeleton.muscles[i].oldrotate2*(1-target)+skeleton.muscles[i].newrotate2*(target);
+ skeleton.muscles[i].rotate3=skeleton.muscles[i].oldrotate3*(1-target)+skeleton.muscles[i].newrotate3*(target);
+ }
+ }
+ }
+
+ if(isLanding()&&landhard){
+ //if(abs(velocity.y)>fast_sqrt(velocity.x*velocity.x*velocity.z*velocity.z)){
+ if(id==0)camerashake+=.4;
+ targetanimation=getLandhard();
+ targetframe=0;
+ target=0;
+ landhard=0;
+ transspeed=15;
+ //}
+ }
+ }
+ //skeleton.DoConstraints();
+}
+
+void Person::DoStuff(){
+ static XYZ terrainnormal;
+ static XYZ flatfacing;
+ static XYZ flatvelocity;
+ static float flatvelspeed;
+ static int i,j,l;
+ static XYZ average;
+ static int howmany;
+ static int bloodsize;
+ static int startx,starty,endx,endy;
+ static int texdetailint;
+ static GLubyte color;
+ static XYZ bloodvel;
+
+ onfiredelay-=multiplier;
+ if(onfiredelay<0&&onfire)
+ {
+ if(Random()%2==0){
+ crouchkeydown=1;
+ }
+ onfiredelay=0.3;
+ }
+
+ crouchkeydowntime+=multiplier;
+ if(!crouchkeydown)crouchkeydowntime=0;
+ jumpkeydowntime+=multiplier;
+ if(!jumpkeydown&&skeleton.free)jumpkeydowntime=0;
+
+ if(hostile||damage>0||bloodloss>0)immobile=0;
+
+ if(isIdle()||isRun())targetoffset=0;
+
+ if(num_weapons==1&&weaponactive!=-1)weaponstuck=-1;
+
+ if(id==0)blooddimamount-=multiplier*.3;
+ speechdelay-=multiplier;
+ texupdatedelay-=multiplier;
+ interestdelay-=multiplier;
+ flamedelay-=multiplier;
+ parriedrecently-=multiplier;
+ if(!victim){
+ victim=this;
+ hasvictim=0;
+ }
+
+ if(id==0)speed=1.1*speedmult;
+ else speed=1.0*speedmult;
+ if(!skeleton.free)rabbitkickragdoll=0;
+
+ speed*=speedmult;
+
+ if(id!=0&&(creature==rabbittype||difficulty!=2))superruntoggle=0;
+ if(id!=0&&creature==wolftype&&difficulty==2){
+ superruntoggle=0;
+ if(aitype!=passivetype){
+ superruntoggle=1;
+ if(aitype==attacktypecutoff&&(player[0].isIdle()||player[0].isCrouch()||player[0].skeleton.free||player[0].targetanimation==getupfrombackanim||player[0].targetanimation==getupfromfrontanim||player[0].targetanimation==sneakanim)&&findDistancefast(&coords,&player[0].coords)<16){
+ superruntoggle=0;
+ }
+ }
+ if(scale<0.2)superruntoggle=0;
+ if(targetanimation==wolfrunninganim&&!superruntoggle){
+ targetanimation=getRun();
+ targetframe=0;
+ }
+ /*static float toggledelay;
+ toggledelay-=multiplier;
+ if(toggledelay<0){
+ toggledelay=1;
+ if(Random()%3==0)superruntoggle=1-superruntoggle;
+ }*/
+ }
+ if(weaponactive==-1&&num_weapons>0){
+ if(weapons.type[weaponids[0]]==staff){
+ weaponactive=0;
+ }
+ }
+
+ if(onfire){
+ burnt+=multiplier;
+ /*if(aitype!=playercontrolled)*///deathbleeding=5;
+ /*if(aitype!=playercontrolled)*/
+ deathbleeding=1;
+ if(burnt>.6)burnt=.6;
+ FSOUND_SetVolume(channels[stream_firesound], 256+256*findLength(&velocity)/3);
+
+ if(targetanimation==jumpupanim||targetanimation==jumpdownanim||isFlip()){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(id==0){
+ FSOUND_3D_SetAttributes(channels[whooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whooshsound], 64*findLength(&velocity)/5);
+ }
+ }
+ }
+ while(flamedelay<0&&onfire){
+ flamedelay+=.006;
+ howmany=abs(Random()%(skeleton.num_joints));
+ if(!skeleton.free)flatvelocity=(coords-oldcoords)/multiplier/2;//velocity/2;
+ if(skeleton.free)flatvelocity=skeleton.joints[howmany].velocity*scale/2;
+ if(!skeleton.free)flatfacing=DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position,0,0,tilt),tilt2,0,0),0,rotation,0)*scale+coords;
+ if(skeleton.free)flatfacing=skeleton.joints[howmany].position*scale+coords;
+ sprites.MakeSprite(flamesprite, flatfacing,flatvelocity, 1,1,1, .6+(float)abs(Random()%100)/200-.25, 1);
+ }
+
+ while(flamedelay<0&&!onfire&&tutoriallevel==1&&id!=0){
+ flamedelay+=.05;
+ howmany=abs(Random()%(skeleton.num_joints));
+ if(!skeleton.free)flatvelocity=(coords-oldcoords)/multiplier/2;//velocity/2;
+ if(skeleton.free)flatvelocity=skeleton.joints[howmany].velocity*scale/2;
+ if(!skeleton.free)flatfacing=DoRotation(DoRotation(DoRotation(skeleton.joints[howmany].position,0,0,tilt),tilt2,0,0),0,rotation,0)*scale+coords;
+ if(skeleton.free)flatfacing=skeleton.joints[howmany].position*scale+coords;
+ sprites.MakeSprite(breathsprite, flatfacing,flatvelocity, 1,1,1, .6+(float)abs(Random()%100)/200-.25, .3);
+ }
+
+ if(bleeding>0){
+ bleeding-=multiplier*.3;
+ if(bloodtoggle==2){
+ glBindTexture(GL_TEXTURE_2D,skeleton.drawmodel.textureptr);
+ if(bleeding<=0&&(detail!=2||osx))DoMipmaps(5,0,0,skeleton.skinsize,skeleton.skinsize);
+ }
+ }
+
+ if(neckspurtamount>0){
+ neckspurtamount-=multiplier;
+ neckspurtdelay-=multiplier*3;
+ neckspurtparticledelay-=multiplier*3;
+ if(neckspurtparticledelay<0&&neckspurtdelay>2){
+ spurt=0;
+ bloodvel=0;
+ if(!skeleton.free){
+ bloodvel.z=5*neckspurtamount;
+ bloodvel=DoRotation(bloodvel,((float)(Random()%100))/40,rotation+((float)(Random()%100))/40,0)*scale;
+ }
+ if(skeleton.free){
+ bloodvel-=DoRotation(skeleton.forward*10*scale,((float)(Random()%100))/40,((float)(Random()%100))/40,0);
+ }
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[head]].velocity,((float)(Random()%100))/40,rotation+((float)(Random()%100))/40,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/40,((float)(Random()%100))/40,0)*scale;
+ if(skeleton.free)sprites.MakeSprite(bloodsprite, (skeleton.joints[skeleton.jointlabels[neck]].position+(skeleton.joints[skeleton.jointlabels[neck]].position-skeleton.joints[skeleton.jointlabels[head]].position)/5)*scale+coords,bloodvel, 1,1,1, .05, .9);
+ if(!skeleton.free)sprites.MakeSprite(bloodsprite, DoRotation(skeleton.joints[skeleton.jointlabels[neck]].position+(skeleton.joints[skeleton.jointlabels[neck]].position-skeleton.joints[skeleton.jointlabels[head]].position)/5,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, .9);
+ neckspurtparticledelay=.05;
+ }
+ if(neckspurtdelay<0){
+ neckspurtdelay=3;
+ }
+ }
+
+ if(deathbleeding>0&&dead!=2){
+ if(deathbleeding<5)bleeddelay-=deathbleeding*multiplier/4;
+ else bleeddelay-=5*multiplier/4;
+ if(bleeddelay<0&&bloodtoggle){
+ bleeddelay=1;
+ XYZ bloodvel;
+ if(bloodtoggle){
+ bloodvel=0;
+ if(skeleton.free)bloodvel+=DoRotation(skeleton.joints[skeleton.jointlabels[abdomen]].velocity,((float)(Random()%100))/4,rotation+((float)(Random()%100))/4,0)*scale;
+ if(!skeleton.free)bloodvel+=DoRotation(velocity,((float)(Random()%100))/4,((float)(Random()%100))/4,0)*scale;
+ if(skeleton.free)sprites.MakeSprite(bloodsprite, skeleton.joints[skeleton.jointlabels[abdomen]].position*scale+coords,bloodvel, 1,1,1, .05, 1);
+ if(!skeleton.free)sprites.MakeSprite(bloodsprite, DoRotation((skeleton.joints[skeleton.jointlabels[abdomen]].position+skeleton.joints[skeleton.jointlabels[abdomen]].position)/2,0,rotation,0)*scale+coords,bloodvel, 1,1,1, .05, 1);
+ }
+ }
+ /*if(id==0){
+ bloodloss+=deathbleeding*40;
+ deathbleeding=0;
+ }*/
+ bloodloss+=deathbleeding*multiplier*80;
+ deathbleeding-=multiplier*1.6;
+ //if(id==0)deathbleeding-=multiplier*.2;
+ if(deathbleeding<0)deathbleeding=0;
+ if(bloodloss>damagetolerance&&animation[targetanimation].attack==neutral){
+ if(weaponactive!=-1){
+ weapons.owner[weaponids[0]]=-1;
+ weapons.velocity[weaponids[0]]=velocity*scale*-.3;
+ weapons.velocity[weaponids[0]].x+=.01;
+ weapons.tipvelocity[weaponids[0]]=velocity*scale;
+ weapons.missed[weaponids[0]]=1;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=1;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ if(weaponstuck==num_weapons)weaponstuck=0;
+ }
+ weaponactive=-1;
+ for(i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+
+ if(id==0){
+ flashamount=.5;
+ flashr=1;
+ flashg=0;
+ flashb=0;
+ flashdelay=0;
+ }
+ }
+
+ if(!dead&&creature==wolftype){
+ bonus=Wolfbonus;
+ bonustime=0;
+ bonusvalue=300;
+ }
+ dead=2;
+ if(targetanimation==knifefollowedanim&&!skeleton.free){
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].velocity=0;
+ skeleton.joints[i].velocity.y=-2;
+ }
+ }
+ if(id!=0&&unconscioustime>.1){
+ numafterkill++;
+ }
+
+ RagDoll(0);
+ }
+ }
+
+ if(texupdatedelay<0&&bleeding>0&&bloodtoggle==2&&findDistancefast(&viewer,&coords)<9){
+ texupdatedelay=.12;
+
+ bloodsize=5-realtexdetail;
+
+ startx=0;
+ starty=0;
+ texdetailint=realtexdetail;
+ startx=bleedy;//abs(Random()%(skeleton.skinsize-bloodsize-1));
+ starty=bleedx;//abs(Random()%(skeleton.skinsize-bloodsize-1));
+ endx=startx+bloodsize;
+ endy=starty+bloodsize;
+
+ if(startx<0){startx=0;bleeding=0;}
+ if(starty<0){starty=0;bleeding=0;}
+ if(endx>skeleton.skinsize-1){endx=skeleton.skinsize-1;bleeding=0;}
+ if(endy>skeleton.skinsize-1){endy=skeleton.skinsize-1;bleeding=0;}
+ if(endx<startx)endx=startx;
+ if(endy<starty)endy=starty;
+ /*int startx=0;
+ int starty=0;
+ int endx=256;
+ int endy=256;*/
+
+ for(i=startx;i<endx;i++){
+ for(j=starty;j<endy;j++){
+ if(Random()%2==0){
+ color=Random()%85+170;
+ if(skeleton.skinText[i*skeleton.skinsize*3+j*3+0]>color/2)skeleton.skinText[i*skeleton.skinsize*3+j*3+0]=color/2;
+ skeleton.skinText[i*skeleton.skinsize*3+j*3+1]=0;
+ skeleton.skinText[i*skeleton.skinsize*3+j*3+2]=0;
+ }
+ }
+ }
+ if(!osx&&detail>1){
+ glBindTexture(GL_TEXTURE_2D,skeleton.drawmodel.textureptr);
+ DoMipmaps(0,startx,endx,starty,endy);
+ }
+
+ if(!skeleton.free){
+ bleedy-=4/realtexdetail;
+ if(detail==2)bleedx+=(abs(Random()%3)-1)*2/realtexdetail;
+ else bleedx+=(abs(Random()%3)-1)*4/realtexdetail;
+ }
+ if(skeleton.free){
+ bleedx+=4*direction/realtexdetail;
+ if(detail==2)bleedy+=(abs(Random()%3)-1)*2/realtexdetail;
+ else bleedy+=(abs(Random()%3)-1)*4/realtexdetail;
+ }
+ }
+
+ if(abs(righthandmorphness-targetrighthandmorphness)<multiplier*4){
+ righthandmorphness=targetrighthandmorphness;
+ righthandmorphstart=righthandmorphend;
+ }
+ else if(righthandmorphness>targetrighthandmorphness){
+ righthandmorphness-=multiplier*4;
+ }
+ else if(righthandmorphness<targetrighthandmorphness){
+ righthandmorphness+=multiplier*4;
+ }
+
+ if(abs(lefthandmorphness-targetlefthandmorphness)<multiplier*4){
+ lefthandmorphness=targetlefthandmorphness;
+ lefthandmorphstart=lefthandmorphend;
+ }
+ else if(lefthandmorphness>targetlefthandmorphness){
+ lefthandmorphness-=multiplier*4;
+ }
+ else if(lefthandmorphness<targetlefthandmorphness){
+ lefthandmorphness+=multiplier*4;
+ }
+
+ if(creature==rabbittype||targettailmorphness==5||targettailmorphness==0){
+ if(abs(tailmorphness-targettailmorphness)<multiplier*10){
+ tailmorphness=targettailmorphness;
+ tailmorphstart=tailmorphend;
+ }
+ else if(tailmorphness>targettailmorphness){
+ tailmorphness-=multiplier*10;
+ }
+ else if(tailmorphness<targettailmorphness){
+ tailmorphness+=multiplier*10;
+ }
+ }
+
+ if(creature==wolftype){
+ if(abs(tailmorphness-targettailmorphness)<multiplier*4){
+ tailmorphness=targettailmorphness;
+ tailmorphstart=tailmorphend;
+ }
+ else if(tailmorphness>targettailmorphness){
+ tailmorphness-=multiplier*2;
+ }
+ else if(tailmorphness<targettailmorphness){
+ tailmorphness+=multiplier*2;
+ }
+ }
+
+ if(headmorphend==3||headmorphstart==3){
+ if(abs(headmorphness-targetheadmorphness)<multiplier*7){
+ headmorphness=targetheadmorphness;
+ headmorphstart=headmorphend;
+ }
+ else if(headmorphness>targetheadmorphness){
+ headmorphness-=multiplier*7;
+ }
+ else if(headmorphness<targetheadmorphness){
+ headmorphness+=multiplier*7;
+ }
+ }
+ else if(headmorphend==5||headmorphstart==5){
+ if(abs(headmorphness-targetheadmorphness)<multiplier*10){
+ headmorphness=targetheadmorphness;
+ headmorphstart=headmorphend;
+ }
+ else if(headmorphness>targetheadmorphness){
+ headmorphness-=multiplier*10;
+ }
+ else if(headmorphness<targetheadmorphness){
+ headmorphness+=multiplier*10;
+ }
+ }
+ else{
+ if(abs(headmorphness-targetheadmorphness)<multiplier*4){
+ headmorphness=targetheadmorphness;
+ headmorphstart=headmorphend;
+ }
+ else if(headmorphness>targetheadmorphness){
+ headmorphness-=multiplier*4;
+ }
+ else if(headmorphness<targetheadmorphness){
+ headmorphness+=multiplier*4;
+ }
+ }
+
+ if(abs(chestmorphness-targetchestmorphness)<multiplier){
+ chestmorphness=targetchestmorphness;
+ chestmorphstart=chestmorphend;
+ }
+ else if(chestmorphness>targetchestmorphness){
+ chestmorphness-=multiplier;
+ }
+ else if(chestmorphness<targetchestmorphness){
+ chestmorphness+=multiplier;
+ }
+
+ if(dead!=2&&howactive<=typesleeping){
+ if(chestmorphstart==0&&chestmorphend==0){
+ chestmorphness=0;
+ targetchestmorphness=1;
+ chestmorphend=3;
+ }
+ if(chestmorphstart!=0&&chestmorphend!=0){
+ chestmorphness=0;
+ targetchestmorphness=1;
+ chestmorphend=0;
+ if(environment==snowyenvironment){
+ XYZ footpoint;
+ XYZ footvel;
+ if(!skeleton.free)footvel=DoRotation(skeleton.specialforward[0],0,rotation,0)*-1;
+ if(skeleton.free)footvel=skeleton.specialforward[0]*-1;
+ if(!skeleton.free)footpoint=DoRotation((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2,0,rotation,0)*scale+coords;
+ if(skeleton.free)footpoint=((skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2)*scale+coords;
+ if(targetanimation==sleepanim)footvel=DoRotation(footvel,0,90,0);
+ sprites.MakeSprite(breathsprite, footpoint+footvel*.2,footvel*.4, 1,1,1, .4, .3);
+ }
+ }
+
+ if(!dead&&howactive<typesleeping){
+ blinkdelay-=multiplier*2;
+ if(headmorphstart==0&&headmorphend==0&&blinkdelay<=0){
+ headmorphness=0;
+ targetheadmorphness=1;
+ headmorphend=3;
+ blinkdelay=(float)(abs(Random()%40))/5;
+ }
+ if(headmorphstart==3&&headmorphend==3){
+ headmorphness=0;
+ targetheadmorphness=1;
+ headmorphend=0;
+ }
+ }
+ if(!dead){
+ twitchdelay-=multiplier*1.5;
+ if(targetanimation!=hurtidleanim){
+ if(headmorphstart==0&&headmorphend==0&&twitchdelay<=0){
+ headmorphness=0;
+ targetheadmorphness=1;
+ headmorphend=5;
+ twitchdelay=(float)(abs(Random()%40))/5;
+ }
+ if(headmorphstart==5&&headmorphend==5){
+ headmorphness=0;
+ targetheadmorphness=1;
+ headmorphend=0;
+ }
+ }
+ if((isIdle()||isCrouch())&&targetanimation!=hurtidleanim){
+ twitchdelay3-=multiplier*1;
+ if(Random()%2==0){
+ if(righthandmorphstart==0&&righthandmorphend==0&&twitchdelay3<=0){
+ righthandmorphness=0;
+ targetrighthandmorphness=1;
+ righthandmorphend=1;
+ if(Random()%2==0)twitchdelay3=(float)(abs(Random()%40))/5;
+ }
+ if(righthandmorphstart==1&&righthandmorphend==1){
+ righthandmorphness=0;
+ targetrighthandmorphness=1;
+ righthandmorphend=0;
+ }
+ }
+ if(Random()%2==0){
+ if(lefthandmorphstart==0&&lefthandmorphend==0&&twitchdelay3<=0){
+ lefthandmorphness=0;
+ targetlefthandmorphness=1;
+ lefthandmorphend=1;
+ twitchdelay3=(float)(abs(Random()%40))/5;
+ }
+ if(lefthandmorphstart==1&&lefthandmorphend==1){
+ lefthandmorphness=0;
+ targetlefthandmorphness=1;
+ lefthandmorphend=0;
+ }
+ }
+ }
+ }
+ if(!dead){
+ if(creature==rabbittype){
+ if(howactive<typesleeping)twitchdelay2-=multiplier*1.5;
+ else twitchdelay2-=multiplier*0.5;
+ if(howactive<=typesleeping){
+ if(tailmorphstart==0&&tailmorphend==0&&twitchdelay2<=0){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=1;
+ twitchdelay2=(float)(abs(Random()%40))/5;
+ }
+ if(tailmorphstart==1&&tailmorphend==1){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=2;
+ }
+ if(tailmorphstart==2&&tailmorphend==2){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=0;
+ }
+ }
+ }
+ }
+ }
+ if(creature==wolftype){
+ twitchdelay2-=multiplier*1.5;
+ if(tailmorphend!=0)
+ if((isRun()||targetanimation==jumpupanim||targetanimation==jumpdownanim||targetanimation==backflipanim)&&!skeleton.free){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=0;
+ twitchdelay2=.1;
+ }
+ if(tailmorphend!=5)
+ if(targetanimation==flipanim||targetanimation==frontflipanim||targetanimation==rollanim||skeleton.free){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=5;
+ twitchdelay2=.1;
+ }
+ if(twitchdelay2<=0){
+ if(((tailmorphstart==0&&tailmorphend==0)||(tailmorphstart==5&&tailmorphend==5))){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=1;
+ }
+ if(tailmorphstart==1&&tailmorphend==1){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=2;
+ }
+ if(tailmorphstart==2&&tailmorphend==2){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=3;
+ }
+ if(tailmorphstart==3&&tailmorphend==3){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=4;
+ }
+ if(tailmorphstart==4&&tailmorphend==4){
+ tailmorphness=0;
+ targettailmorphness=1;
+ tailmorphend=1;
+ }
+ }
+ }
+
+ if(dead!=1)unconscioustime=0;
+
+ if(dead==1||howactive==typesleeping){
+ unconscioustime+=multiplier;
+ //If unconscious, close eyes and mouth
+ if(righthandmorphend!=0)righthandmorphness=0;
+ righthandmorphend=0;
+ targetrighthandmorphness=1;
+
+ if(lefthandmorphend!=0)lefthandmorphness=0;
+ lefthandmorphend=0;
+ targetlefthandmorphness=1;
+
+ if(headmorphend!=3&&headmorphend!=5)headmorphness=0;
+ headmorphend=3;
+ targetheadmorphness=1;
+ }
+
+
+ if(howactive>typesleeping){
+ XYZ headpoint;
+ headpoint=coords;
+ if(bloodtoggle&&!bled){
+ terrain.MakeDecal(blooddecalslow,headpoint,.8,.5,0);
+ }
+ if(bloodtoggle&&!bled)
+ for(l=0;l<terrain.patchobjectnum[whichpatchx][whichpatchz];l++){
+ j=terrain.patchobjects[whichpatchx][whichpatchz][l];
+ XYZ point=DoRotation(headpoint-objects.position[j],0,-objects.rotation[j],0);
+ float size=.8;
+ float opacity=.6;
+ float rotation=0;
+ objects.model[j].MakeDecal(blooddecalslow,&point,&size,&opacity,&rotation);
+ }
+ bled=1;
+ }
+
+ if(dead==2||howactive>typesleeping){
+ //If dead, open mouth and hands
+ if(righthandmorphend!=0)righthandmorphness=0;
+ righthandmorphend=0;
+ targetrighthandmorphness=1;
+
+ if(lefthandmorphend!=0)lefthandmorphness=0;
+ lefthandmorphend=0;
+ targetlefthandmorphness=1;
+
+ if(headmorphend!=2)headmorphness=0;
+ headmorphend=2;
+ targetheadmorphness=1;
+ }
+
+ if(stunned>0&&!dead&&headmorphend!=2){
+ if(headmorphend!=4)headmorphness=0;
+ headmorphend=4;
+ targetheadmorphness=1;
+ }
+
+ if(damage>damagetolerance&&!dead){
+
+ dead=1;
+ unconscioustime=0;
+
+ if(creature==wolftype){
+ bonus=Wolfbonus;
+ bonustime=0;
+ bonusvalue=300;
+ }
+
+ RagDoll(0);
+
+ if(weaponactive!=-1){
+ weapons.owner[weaponids[0]]=-1;
+ weapons.velocity[weaponids[0]]=velocity*scale*-.3;
+ weapons.velocity[weaponids[0]].x+=.01;
+ weapons.tipvelocity[weaponids[0]]=velocity*scale;
+ weapons.missed[weaponids[0]]=1;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=1;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ if(weaponstuck==num_weapons)weaponstuck=0;
+ }
+ weaponactive=-1;
+ for(i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+ }
+
+
+
+ if((id==0||findDistancefast(&coords,&viewer)<50)&&autoslomo){
+ slomo=1;
+ slomodelay=.2;
+ }
+
+ damage+=20;
+
+ /*
+ if(bloodloss<damagetolerance)
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].velocity*=1.5;
+ }*/
+ }
+
+ //if(dead)damage-=multiplier/4;
+ if(!dead)damage-=multiplier*13;
+ //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
+ if(!dead)permanentdamage-=multiplier*4;
+ if(isIdle()||isCrouch()){
+ if(!dead)permanentdamage-=multiplier*4;
+ //if(!dead&&deathbleeding<=0&&id==0)bloodloss-=multiplier*4;
+ }
+ if(damage<0)damage=0;
+ if(permanentdamage<0)permanentdamage=0;
+ if(superpermanentdamage<0)superpermanentdamage=0;
+ if(permanentdamage<superpermanentdamage){
+ permanentdamage=superpermanentdamage;
+ }
+ if(damage<permanentdamage){
+ damage=permanentdamage;
+ }
+ if(dead==1&&damage<damagetolerance){
+ dead=0;
+ skeleton.free=1;
+ damage-=20;
+ for(i=0;i<skeleton.num_joints;i++){
+ skeleton.joints[i].velocity=0;
+ }
+ }
+ if(permanentdamage>damagetolerance&&dead!=2){
+ DoBlood(1,255);
+
+ if(weaponactive!=-1){
+ weapons.owner[weaponids[0]]=-1;
+ weapons.velocity[weaponids[0]]=velocity*scale*-.3;
+ weapons.velocity[weaponids[0]].x+=.01;
+ weapons.tipvelocity[weaponids[0]]=velocity*scale;
+ weapons.missed[weaponids[0]]=1;
+ weapons.hitsomething[weaponids[0]]=0;
+ weapons.freetime[weaponids[0]]=0;
+ weapons.firstfree[weaponids[0]]=1;
+ weapons.physics[weaponids[0]]=1;
+ num_weapons--;
+ if(num_weapons){
+ weaponids[0]=weaponids[num_weapons];
+ if(weaponstuck==num_weapons)weaponstuck=0;
+ }
+ weaponactive=-1;
+ for(i=0;i<numplayers;i++){
+ player[i].wentforweapon=0;
+ }
+ }
+
+ bled=0;
+
+ if(!dead&&creature==wolftype){
+ bonus=Wolfbonus;
+ bonustime=0;
+ bonusvalue=300;
+ }
+
+ if(id!=0&&unconscioustime<.1&&(bonus!=spinecrusher||bonustime>1)&&(bonus!=FinishedBonus||bonustime>1)&&bloodloss<damagetolerance){
+ bonus=touchofdeath;
+ bonustime=0;
+ bonusvalue=150;
+ }
+ if(id!=0&&unconscioustime>.1){
+ numafterkill++;
+ }
+
+ dead=2;
+
+ skeleton.free=1;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( breaksound, samp[breaksound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound], 512);
+ FSOUND_SetPaused(channels[breaksound], FALSE);
+ /*if(id==0||findDistancefast(&coords,&viewer)<50){
+ slomo=1;
+ slomodelay=.2;
+ }*/
+ }
+
+ if(skeleton.free==1){
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+
+ if(!dead){
+ //If knocked over, open hands and close mouth
+ if(righthandmorphend!=0)righthandmorphness=0;
+ righthandmorphend=0;
+ targetrighthandmorphness=1;
+
+ if(lefthandmorphend!=0)lefthandmorphness=0;
+ lefthandmorphend=0;
+ targetlefthandmorphness=1;
+
+ if(headmorphend!=3&&headmorphend!=5&&headmorphstart!=3&&headmorphstart!=5){
+ if(headmorphend!=0)headmorphness=0;
+ headmorphend=0;
+ targetheadmorphness=1;
+ }
+ }
+
+ skeleton.DoGravity(&scale);
+ float damageamount;
+ damageamount=skeleton.DoConstraints(&coords,&scale)*5;
+ if(id!=0&&damage>damagetolerance-damageamount&&!dead&&(bonus!=spinecrusher||bonustime>1)&&(bonus!=style||bonustime>1)&&(bonus!=cannon||bonustime>1)){
+ bonus=deepimpact;
+ bonustime=0;
+ bonusvalue=50;
+ }
+ DoDamage(damageamount/((protectionhigh+protectionhead+protectionlow)/3));
+
+ average=0;
+ howmany=0;
+ for(j=0;j<skeleton.num_joints;j++){
+ average+=skeleton.joints[j].position;
+ howmany++;
+ }
+ average/=howmany;
+ coords+=average*scale;
+ for(j=0;j<skeleton.num_joints;j++){
+ skeleton.joints[j].position-=average;
+ }
+ average/=multiplier;
+
+ //velocity=skeleton.joints[skeleton.jointlabels[groin]].velocity*scale;
+ velocity=0;
+ for(i=0;i<skeleton.num_joints;i++){
+ velocity+=skeleton.joints[i].velocity*scale;
+ }
+ velocity/=skeleton.num_joints;
+
+ if(!isnormal(velocity.x)&&velocity.x){
+ velocity=0;
+ }
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+
+ if(findLength(&average)<10&&dead&&skeleton.free){
+ skeleton.longdead+=(2000-findLength(&average))*multiplier+multiplier;
+ if(skeleton.longdead>2000){
+ if(skeleton.longdead>6000){
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+ skeleton.free=3;
+ DrawSkeleton();
+ skeleton.free=2;
+ }
+ if(dead==2&&bloodloss<damagetolerance){
+ XYZ headpoint;
+ headpoint=(skeleton.joints[skeleton.jointlabels[head]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2*scale+coords;
+ DoBlood(1,255);
+ if(bloodtoggle&&!bled){
+ terrain.MakeDecal(blooddecal,headpoint,.2*1.2,.5,0);
+ }
+ if(bloodtoggle&&!bled)
+ for(l=0;l<terrain.patchobjectnum[whichpatchx][whichpatchz];l++){
+ j=terrain.patchobjects[whichpatchx][whichpatchz][l];
+ XYZ point=DoRotation(headpoint-objects.position[j],0,-objects.rotation[j],0);
+ float size=.2*1.2;
+ float opacity=.6;
+ float rotation=0;
+ objects.model[j].MakeDecal(blooddecal,&point,&size,&opacity,&rotation);
+ }
+ bled=1;
+ }
+ if(dead==2&&bloodloss>=damagetolerance){
+ XYZ headpoint;
+ headpoint=(skeleton.joints[skeleton.jointlabels[abdomen]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2*scale+coords;
+ if(bleeding<=0)DoBlood(1,255);
+ if(bloodtoggle&&!bled){
+ terrain.MakeDecal(blooddecalslow,headpoint,.8,.5,0);
+ }
+ if(bloodtoggle&&!bled)
+ for(l=0;l<terrain.patchobjectnum[whichpatchx][whichpatchz];l++){
+ j=terrain.patchobjects[whichpatchx][whichpatchz][l];
+ XYZ point=DoRotation(headpoint-objects.position[j],0,-objects.rotation[j],0);
+ float size=.8;
+ float opacity=.6;
+ float rotation=0;
+ objects.model[j].MakeDecal(blooddecalslow,&point,&size,&opacity,&rotation);
+ }
+ bled=1;
+ }
+ }
+ }
+
+ if(!dead&&crouchkeydown&&skeleton.freetime>.5&&id==0&&skeleton.free){
+ bool canrecover=1;
+ XYZ startpoint,endpoint,colpoint,colviewer,coltarget;
+ startpoint=coords;
+ endpoint=coords;
+ endpoint.y-=.7;
+ if(terrain.lineTerrain(startpoint,endpoint,&colpoint)!=-1)canrecover=0;
+ if(velocity.y<-30)canrecover=0;
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]!=treeleavestype&&objects.type[i]!=bushtype&&objects.type[i]!=firetype){
+ colviewer=startpoint;
+ coltarget=endpoint;
+ if(objects.model[i].LineCheck(&colviewer,&coltarget,&colpoint,&objects.position[i],&objects.rotation[i])!=-1)canrecover=0;
+ }
+ }
+ if(canrecover){
+ skeleton.free=0;
+ XYZ middle;
+ middle=0;
+
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[abdomen]].position;
+ if(skeleton.joints[skeleton.jointlabels[groin]].locked&&skeleton.joints[skeleton.jointlabels[abdomen]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[abdomen]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[groin]].position+skeleton.joints[skeleton.jointlabels[abdomen]].position)/2;
+ }
+ if(skeleton.joints[skeleton.jointlabels[abdomen]].locked&&skeleton.joints[skeleton.jointlabels[neck]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[abdomen]].position-skeleton.joints[skeleton.jointlabels[neck]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[neck]].position+skeleton.joints[skeleton.jointlabels[abdomen]].position)/2;
+ }
+ if(skeleton.joints[skeleton.jointlabels[groin]].locked&&skeleton.joints[skeleton.jointlabels[neck]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[neck]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[groin]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2;
+ }
+ Normalise(&terrainnormal);
+
+ targetrotation=-asin(0-terrainnormal.x);
+ targetrotation*=360/6.28;
+ if(terrainnormal.z<0)targetrotation=180-targetrotation;
+ rotation=targetrotation;
+
+ //if(skeleton.forward.y<0){
+ targetframe=0;
+ //}
+ //if(skeleton.forward.y>-.3){
+ // targetframe=2;
+ //}
+ targetanimation=flipanim;
+ crouchtogglekeydown=1;
+ target=0;
+ tilt2=0;
+ targettilt2=0;
+
+ currentanimation=tempanim;
+ currentframe=0;
+ target=0;
+ //tilt2=targettilt2;
+
+ //if(middle.y>0)targetoffset.y=middle.y+1;
+
+ for(i=0;i<skeleton.num_joints;i++){
+ tempanimation.position[i][0]=skeleton.joints[i].position;
+ tempanimation.position[i][0]=DoRotation(tempanimation.position[i][0],0,-rotation,0);
+ }
+ }
+ }
+
+ if(findLength(&average)<10&&!dead&&skeleton.free){
+ skeleton.longdead+=(2000-findLength(&average))*multiplier+multiplier;
+ if(skeleton.longdead>(damage+500)*1.5){
+ if(id==0)FSOUND_SetPaused(channels[whooshsound], TRUE);
+ skeleton.free=0;
+ velocity=0;
+ XYZ middle;
+ middle=0;
+
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[abdomen]].position;
+ if(skeleton.joints[skeleton.jointlabels[groin]].locked&&skeleton.joints[skeleton.jointlabels[abdomen]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[abdomen]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[groin]].position+skeleton.joints[skeleton.jointlabels[abdomen]].position)/2;
+ }
+ if(skeleton.joints[skeleton.jointlabels[abdomen]].locked&&skeleton.joints[skeleton.jointlabels[neck]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[abdomen]].position-skeleton.joints[skeleton.jointlabels[neck]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[neck]].position+skeleton.joints[skeleton.jointlabels[abdomen]].position)/2;
+ }
+ if(skeleton.joints[skeleton.jointlabels[groin]].locked&&skeleton.joints[skeleton.jointlabels[neck]].locked){
+ terrainnormal=skeleton.joints[skeleton.jointlabels[groin]].position-skeleton.joints[skeleton.jointlabels[neck]].position;
+ middle=(skeleton.joints[skeleton.jointlabels[groin]].position+skeleton.joints[skeleton.jointlabels[neck]].position)/2;
+ }
+ Normalise(&terrainnormal);
+
+ targetrotation=-asin(0-terrainnormal.x);
+ targetrotation*=360/6.28;
+ if(terrainnormal.z<0)targetrotation=180-targetrotation;
+ rotation=targetrotation;
+
+ /*if(onterrain){
+ terrainnormal=terrain.getNormal(coords.x,coords.z);
+ targettilt2=asin(terrainnormal.y)*180/3.14*-1;
+ }
+ else*/
+
+ /*XYZ otherterrainnormal;
+ otherterrainnormal=terrain.getNormal(coords.x,coords.y);
+ otherterrainnormal.y=fast_sqrt(otherterrainnormal.x*otherterrainnormal.x+otherterrainnormal.z*otherterrainnormal.z)*-1;
+ if(abs(terrainnormal.y)<abs(otherterrainnormal.y))terrainnormal.y=fast_sqrt(otherterrainnormal.x*otherterrainnormal.x+otherterrainnormal.z*otherterrainnormal.z)*-1;
+ targettilt2=asin(otherterrainnormal.y)*180/3.14;
+ */
+
+ targettilt2=asin(terrainnormal.y)*180/3.14*-1;
+
+
+
+ if(skeleton.forward.y<0){
+ targetanimation=getupfrombackanim;
+ targetframe=0;
+ targettilt2=0;
+ }
+ if(skeleton.forward.y>-.3){
+ targetanimation=getupfromfrontanim;
+ rotation+=180;
+ targetrotation+=180;
+ targettilt2*=-1;
+ targetframe=0;
+ targettilt2=0;
+ }
+
+ if((Random()%8==0&&id!=0&&creature==rabbittype)||(Random()%2==0&&id!=0&&creature==wolftype)||(id==0&&crouchkeydown&&(forwardkeydown||backkeydown||leftkeydown||rightkeydown))){
+ targetanimation=rollanim;
+ targetrotation=lookrotation;
+ if(id==0){
+ if(rightkeydown){
+ targetrotation-=90;
+ if(forwardkeydown)targetrotation+=45;
+ if(backkeydown)targetrotation-=45;
+ }
+ if(leftkeydown){
+ targetrotation+=90;
+ if(forwardkeydown)targetrotation-=45;
+ if(backkeydown)targetrotation+=45;
+ }
+ if(backkeydown){
+ if ( !leftkeydown&&!rightkeydown)
+ targetrotation+=180;
+ }
+ targetrotation+=180;
+ }
+ }
+
+ if(abs(targettilt2)>50)targettilt2=0;
+ currentanimation=tempanim;
+ currentframe=0;
+ target=0;
+ tilt2=targettilt2;
+
+ if(middle.y>0&&targetanimation!=rollanim)targetoffset.y=middle.y+1;
+
+ for(i=0;i<skeleton.num_joints;i++){
+ tempanimation.position[i][0]=skeleton.joints[i].position;
+ tempanimation.position[i][0]=DoRotation(tempanimation.position[i][0],0,-rotation,0);
+ }
+ }
+ }
+
+ bool hasstaff;
+ hasstaff=0;
+ if(num_weapons>0)if(weapons.type[0]==staff)hasstaff=1;
+ if(!skeleton.freefall&&freefall&&((jumpkeydown&&jumpkeydowntime<.2)||(hasstaff&&rabbitkickragdoll))&&!dead){
+ if(velocity.y>-30){
+ XYZ tempvelocity;
+ tempvelocity=velocity;
+ Normalise(&tempvelocity);
+ targetrotation=-asin(0-tempvelocity.x);
+ targetrotation*=360/6.28;
+ if(velocity.z<0)targetrotation=180-targetrotation;
+ //targetrotation+=180;
+
+ skeleton.free=0;
+ if(dotproduct(&skeleton.forward,&tempvelocity)<0){
+ targetanimation=rollanim;
+ targetframe=2;
+ }
+ else{
+ targetanimation=backhandspringanim;
+ targetrotation+=180;
+ targetframe=6;
+ }
+ target=0;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( movewhooshsound, samp[movewhooshsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[movewhooshsound], gLoc, vel);
+ FSOUND_SetVolume(channels[movewhooshsound], 128);
+ FSOUND_SetPaused(channels[movewhooshsound], FALSE);
+
+ currentanimation=targetanimation;
+ currentframe=targetframe-1;
+ target=0;
+
+ velocity=0;
+
+ rotation=targetrotation;
+ tilt=0;
+ targettilt=0;
+ tilt2=0;
+ targettilt2=0;
+ }
+ }
+ if(skeleton.freefall==0)freefall=0;
+
+ if(!isnormal(velocity.x)&&velocity.x){
+ int xy=1;
+ }
+ }
+
+ if(aitype!=passivetype||skeleton.free==1)
+ if(findLengthfast(&velocity)>.1)
+ for(i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==firetype)
+ if(findDistancefastflat(&coords,&objects.position[i])<objects.scale[i]*objects.scale[i]*12&&findDistancefast(&coords,&objects.position[i])<objects.scale[i]*objects.scale[i]*49){
+ if(onfire){
+ if(!objects.onfire[i]){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=objects.position[i].x;
+ gLoc[1]=objects.position[i].y;
+ gLoc[2]=objects.position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ }
+ objects.onfire[i]=1;
+ }
+ if(!onfire){
+ if(objects.onfire[i]){
+ CatchFire();
+ }
+ }
+ }
+ if(objects.type[i]==bushtype)
+ if(findDistancefastflat(&coords,&objects.position[i])<objects.scale[i]*objects.scale[i]*12&&findDistancefast(&coords,&objects.position[i])<objects.scale[i]*objects.scale[i]*49){
+ if(onfire){
+ if(!objects.onfire[i]){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=objects.position[i].x;
+ gLoc[1]=objects.position[i].y;
+ gLoc[2]=objects.position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ }
+ objects.onfire[i]=1;
+ }
+
+ if(!onfire){
+ if(objects.onfire[i]){
+ CatchFire();
+ }
+ }
+ if(objects.messedwith[i]<=0){
+ XYZ tempvel;
+ XYZ pos;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( bushrustle, samp[bushrustle], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[bushrustle], gLoc, vel);
+ FSOUND_SetVolume(channels[bushrustle], 40*findLength(&velocity));
+ FSOUND_SetPaused(channels[bushrustle], FALSE);
+
+ if(id==0){
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=4*findLength(&velocity);
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ int howmany;
+ if(environment==grassyenvironment)howmany=findLength(&velocity)*4;
+ if(environment==snowyenvironment)howmany=findLength(&velocity)*2;
+ if(detail==2)
+ if(environment!=desertenvironment)
+ for(j=0;j<howmany;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ pos=coords;
+ pos.y+=1;
+ pos.x+=float(abs(Random()%100)-50)/200;
+ pos.y+=float(abs(Random()%100)-50)/200;
+ pos.z+=float(abs(Random()%100)-50)/200;
+ sprites.MakeSprite(splintersprite, pos,tempvel*.5+velocity*float(abs(Random()%100))/100, 165/255+float(abs(Random()%100)-50)/400,0,0, .2+float(abs(Random()%100)-50)/1300, 1);
+ sprites.special[sprites.numsprites-1]=1;
+ }
+ howmany=findLength(&velocity)*4;
+ if(detail==2)
+ if(environment==snowyenvironment)
+ for(j=0;j<howmany;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ pos=coords;
+ pos.y+=1;
+ pos.x+=float(abs(Random()%100)-50)/200;
+ pos.y+=float(abs(Random()%100)-50)/200;
+ pos.z+=float(abs(Random()%100)-50)/200;
+ sprites.MakeSprite(splintersprite, pos,tempvel*.3+velocity*float(abs(Random()%100))/100/2, 1,1,1, .1, 1);
+ sprites.special[sprites.numsprites-1]=2;
+ }
+ }
+ objects.rotx[i]+=velocity.x*multiplier*6;
+ objects.roty[i]+=velocity.z*multiplier*6;
+ objects.messedwith[i]=.5;
+ }
+ XYZ tempcoord;
+ if(objects.type[i]==treeleavestype&&environment!=desertenvironment){
+ if(objects.rotation2[i]==0)tempcoord=coords;
+ else{
+ tempcoord=coords-objects.position[i];
+ tempcoord=DoRotation(tempcoord,0,-objects.rotation[i],0);
+ tempcoord=DoRotation(tempcoord,-objects.rotation2[i],0,0);
+ tempcoord+=objects.position[i];
+ }
+ if(findDistancefastflat(&tempcoord,&objects.position[i])<objects.scale[i]*objects.scale[i]*8&&findDistancefast(&tempcoord,&objects.position[i])<objects.scale[i]*objects.scale[i]*300&&tempcoord.y>objects.position[i].y+3*objects.scale[i]){
+ /*if(onfire){
+ if(!objects.onfire[i]){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=objects.position[i].x;
+ gLoc[1]=objects.position[i].y;
+ gLoc[2]=objects.position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( firestartsound, samp[firestartsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[firestartsound], gLoc, vel);
+ FSOUND_SetVolume(channels[firestartsound], 256);
+ FSOUND_SetPaused(channels[firestartsound], FALSE);
+ objects.onfire[i]=1;
+ }
+ }*/
+ if(objects.messedwith[i]<=0){
+ XYZ tempvel;
+ XYZ pos;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( bushrustle, samp[bushrustle], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[bushrustle], gLoc, vel);
+ FSOUND_SetVolume(channels[bushrustle], 40*findLength(&velocity));
+ FSOUND_SetPaused(channels[bushrustle], FALSE);
+
+ if(id==0){
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=4*findLength(&velocity);
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ int howmany;
+ if(environment==grassyenvironment)howmany=findLength(&velocity)*4;
+ if(environment==snowyenvironment)howmany=findLength(&velocity)*2;
+ if(detail==2)
+ if(environment!=desertenvironment)
+ for(j=0;j<howmany;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ pos=coords;
+ pos+=velocity*.1;
+ pos.y+=1;
+ pos.x+=float(abs(Random()%100)-50)/150;
+ pos.y+=float(abs(Random()%100)-50)/150;
+ pos.z+=float(abs(Random()%100)-50)/150;
+ sprites.MakeSprite(splintersprite, pos,tempvel*.5+velocity*float(abs(Random()%100))/100, 165/255+float(abs(Random()%100)-50)/400,0,0, .2+float(abs(Random()%100)-50)/1300, 1);
+ sprites.special[sprites.numsprites-1]=1;
+ }
+ howmany=findLength(&velocity)*4;
+ if(detail==2)
+ if(environment==snowyenvironment)
+ for(j=0;j<howmany;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ pos=coords;
+ pos+=velocity*.1;
+ pos.y+=1;
+ pos.x+=float(abs(Random()%100)-50)/150;
+ pos.y+=float(abs(Random()%100)-50)/150;
+ pos.z+=float(abs(Random()%100)-50)/150;
+ sprites.MakeSprite(splintersprite, pos,tempvel*.3+velocity*float(abs(Random()%100))/100/2, 1,1,1, .1, 1);
+ sprites.special[sprites.numsprites-1]=2;
+ }
+ }
+ objects.messedwith[i]=.5;
+ }
+ }
+ }
+
+ if(!skeleton.free){
+ bool play;
+ play=0;
+ if((stunned>0||surprised>0)&&numplayers>2&&aitype!=passivetype)play=1;
+ if(hasvictim)
+ if(aitype!=passivetype&&victim->skeleton.free&&!victim->dead)play=1;
+ if(tutoriallevel==1&&id!=0)play=0;
+ if(play&&aitype!=playercontrolled){
+ int whichsound=-1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ i=abs(Random()%4);
+ if(speechdelay<=0){
+ if(creature==rabbittype){
+ if(i==0)whichsound=rabbitchitter;
+ if(i==1)whichsound=rabbitchitter2;
+ }
+ if(creature==wolftype){
+ if(i==0)whichsound=growlsound;
+ if(i==1)whichsound=growl2sound;
+ }
+ }
+ speechdelay=.3;
+ //else if(animation[targetanimation].label[targetframe]==4)whichsound=knifeswishsound;
+ //if(animation[targetanimation].label[targetframe]==8)whichsound=landsound2;
+
+ if(whichsound!=-1){
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 512);
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+ if(targetanimation==staggerbackhighanim)staggerdelay=1;
+ if(targetanimation==staggerbackhardanim)staggerdelay=1;
+ staggerdelay-=multiplier;
+ if(targetanimation!=crouchstabanim&&targetanimation!=swordgroundstabanim&&targetanimation!=staffgroundsmashanim)hasvictim=1;
+ if(velocity.y<-30&&targetanimation==jumpdownanim)RagDoll(0);
+ if(currentanimation!=getIdle()&&wasIdle()&&targetanimation!=getIdle()&&isIdle()){
+ targetanimation=getIdle();
+ targetframe=0;
+ target=0;
+ }
+ weaponmissdelay-=multiplier;
+ highreversaldelay-=multiplier;
+ lowreversaldelay-=multiplier;
+ lastcollide-=multiplier;
+ skiddelay-=multiplier;
+ if(!isnormal(velocity.x)&&velocity.x){
+ velocity=0;
+ }
+ if(!isnormal(targettilt)&&targettilt){
+ targettilt=0;
+ }
+ if(!isnormal(targettilt2)&&targettilt2){
+ targettilt2=0;
+ }
+ if(!isnormal(targetrotation)&&targetrotation){
+ targetrotation=0;
+ }
+
+ if(targetanimation==bounceidleanim||targetanimation==wolfidle||targetanimation==walkanim||targetanimation==drawrightanim||targetanimation==crouchdrawrightanim||targetanimation==drawleftanim||targetanimation==fightidleanim||targetanimation==fightsidestep||targetanimation==hanganim||isCrouch()||targetanimation==backhandspringanim){
+ //open hands and close mouth
+ //if(targetanimation!=wolfidle){
+ if(righthandmorphend!=0&&righthandmorphness==targetrighthandmorphness){
+ righthandmorphness=0;
+ righthandmorphend=0;
+ targetrighthandmorphness=1;
+ }
+
+ if(lefthandmorphend!=0&&lefthandmorphness==targetlefthandmorphness){
+ lefthandmorphness=0;
+ lefthandmorphend=0;
+ targetlefthandmorphness=1;
+ }
+ //s}
+
+ if(headmorphend!=3&&headmorphend!=5&&headmorphstart!=3&&headmorphstart!=5&&headmorphend!=0&&headmorphness==targetheadmorphness){
+ headmorphness=0;
+ headmorphend=0;
+ targetheadmorphness=1;
+ }
+ }
+
+ if(targetanimation==rollanim||targetanimation==dodgebackanim||targetanimation==removeknifeanim||targetanimation==knifefightidleanim||targetanimation==swordfightidleanim||targetanimation==blockhighleftstrikeanim||targetanimation==crouchremoveknifeanim||targetanimation==sneakanim||targetanimation==sweepanim||targetanimation==spinkickreversedanim||targetanimation==jumpdownanim||isWallJump()||isFlip()||targetanimation==climbanim||isRun()||targetanimation==getupfrombackanim||targetanimation==getupfromfrontanim){
+ //open hands and mouth
+ if(righthandmorphend!=0&&righthandmorphness==targetrighthandmorphness){
+ righthandmorphness=0;
+ righthandmorphend=0;
+ targetrighthandmorphness=1;
+ }
+
+ if(lefthandmorphend!=0&&lefthandmorphness==targetlefthandmorphness){
+ lefthandmorphness=0;
+ lefthandmorphend=0;
+ targetlefthandmorphness=1;
+ }
+
+ if(headmorphend!=1&&headmorphness==targetheadmorphness){
+ headmorphness=0;
+ headmorphend=1;
+ targetheadmorphness=1;
+ }
+ }
+
+ if(targetanimation==jumpupanim||targetanimation==crouchstabanim||targetanimation==swordgroundstabanim||targetanimation==swordfightidlebothanim||targetanimation==blockhighleftanim||targetanimation==blockhighleftanim){
+ //close hands and mouth
+ if(righthandmorphend!=1&&righthandmorphness==targetrighthandmorphness){
+ righthandmorphness=0;
+ righthandmorphend=1;
+ targetrighthandmorphness=1;
+ }
+
+ if(lefthandmorphend!=1&&lefthandmorphness==targetlefthandmorphness){
+ lefthandmorphness=0;
+ lefthandmorphend=1;
+ targetlefthandmorphness=1;
+ }
+
+ if(headmorphend!=0&&headmorphness==targetheadmorphness){
+ headmorphness=0;
+ headmorphend=0;
+ targetheadmorphness=1;
+ }
+ }
+
+ if(targetanimation==spinkickanim||targetanimation==staffspinhitreversalanim||targetanimation==staffspinhitreversedanim||targetanimation==staffhitreversalanim||targetanimation==staffhitreversedanim||targetanimation==hurtidleanim||targetanimation==winduppunchanim||targetanimation==swordslashreversalanim||targetanimation==swordslashreversedanim||targetanimation==knifeslashreversalanim||targetanimation==knifeslashreversedanim||targetanimation==knifethrowanim||targetanimation==knifefollowanim||targetanimation==knifefollowedanim||targetanimation==killanim||targetanimation==dropkickanim||targetanimation==upunchanim||targetanimation==knifeslashstartanim||targetanimation==swordslashanim||targetanimation==staffhitanim||targetanimation==staffspinhitanim||targetanimation==staffgroundsmashanim||targetanimation==spinkickreversalanim||targetanimation==sweepreversalanim||targetanimation==lowkickanim||targetanimation==sweepreversedanim||targetanimation==rabbitkickreversalanim||targetanimation==rabbitkickreversedanim||targetanimation==jumpreversalanim||targetanimation==jumpreversedanim){
+ //close hands and yell
+ if(righthandmorphend!=1&&righthandmorphness==targetrighthandmorphness){
+ righthandmorphness=0;
+ righthandmorphend=1;
+ targetrighthandmorphness=1;
+ }
+
+ if(lefthandmorphend!=1&&lefthandmorphness==targetlefthandmorphness){
+ lefthandmorphness=0;
+ lefthandmorphend=1;
+ targetlefthandmorphness=1;
+ }
+
+ if(headmorphend!=2&&headmorphness==targetheadmorphness){
+ headmorphness=1;
+ headmorphend=2;
+ targetheadmorphness=1;
+ }
+ }
+ /*
+ if(speechdelay>.25){
+ if(headmorphend!=2)headmorphness=0;
+ headmorphend=2;
+ targetheadmorphness=1;
+ }
+ */
+ bool behind;
+ behind=0;
+ if(hasvictim){
+ if(victim!=this&&!victim->dead&&victim->aitype!=passivetype&&victim->aitype!=searchtype&&aitype!=passivetype&&aitype!=searchtype&&victim->id<numplayers&&aitype!=passivetype){
+ behind=(normaldotproduct(facing,coords-victim->coords)>0);
+ }
+ }
+
+ if(!dead&&targetanimation!=hurtidleanim)
+ if(behind||targetanimation==killanim||targetanimation==knifethrowanim||targetanimation==knifefollowanim||targetanimation==spinkickreversalanim||targetanimation==rabbitkickreversedanim||targetanimation==jumpreversedanim){
+ if(headmorphend!=4||headmorphness==targetheadmorphness){
+ headmorphend=4;
+ //headmorphness=1;
+ targetheadmorphness=1;
+ }
+ }
+
+ if(weaponactive!=-1){
+ if(weapons.type[weaponids[weaponactive]]!=staff){
+ righthandmorphstart=1;
+ righthandmorphend=1;
+ }
+ if(weapons.type[weaponids[weaponactive]]==staff){
+ righthandmorphstart=2;
+ righthandmorphend=2;
+ }
+ targetrighthandmorphness=1;
+ }
+
+ terrainnormal=terrain.getNormal(coords.x,coords.z);
+
+ if(animation[targetanimation].attack!=reversal){
+ if(!isnormal(coords.x))
+ coords=oldcoords;
+ oldcoords=coords;
+ }
+
+ flatfacing=0;
+ flatfacing.z=1;
+
+ flatfacing=DoRotation(flatfacing,0,rotation,0);
+ facing=flatfacing;
+ ReflectVector(&facing,&terrainnormal);
+ Normalise(&facing);
+
+ if(isRun()||targetanimation==sneakanim||targetanimation==rollanim||targetanimation==walkanim){
+ if(onterrain)targettilt2=-facing.y*20;
+ else targettilt2=0;
+ }
+ onterrain=0;
+ if(!isRun()&&!animation[targetanimation].attack&&targetanimation!=getupfromfrontanim&&targetanimation!=getupfrombackanim&&targetanimation!=sneakanim)targettilt2=0;
+ if(targetanimation==jumpupanim||targetanimation==jumpdownanim||isFlip()){
+ flatvelocity=velocity;
+ flatvelocity.y=0;
+ flatvelspeed=findLength(&flatvelocity);
+ targettilt=flatvelspeed*fast_sqrt(abs(velocity.y)*.7)*normaldotproduct(DoRotation(flatfacing,0,-90,0),flatvelocity);
+ targettilt2=flatvelspeed*fast_sqrt(abs(velocity.y)*.7)*normaldotproduct(flatfacing,flatvelocity);
+ if(velocity.y<0)targettilt2*=-1;
+ if(velocity.y<0)targettilt*=-1;
+ if(targettilt>25)targettilt=25;
+ if(targettilt<-25)targettilt=-25;
+ }
+
+ if(targettilt2>45)targettilt2=45;
+ if(targettilt2<-45)targettilt2=-45;
+ if(abs(tilt2-targettilt2)<multiplier*400)tilt2=targettilt2;
+ else if(tilt2>targettilt2){
+ tilt2-=multiplier*400;
+ }
+ else if(tilt2<targettilt2){
+ tilt2+=multiplier*400;
+ }
+ if(!animation[targetanimation].attack&&targetanimation!=getupfrombackanim&&targetanimation!=getupfromfrontanim){
+ if(tilt2>25)tilt2=25;
+ if(tilt2<-25)tilt2=-25;
+ }
+
+ if(!isnormal(targettilt)&&targettilt){
+ targettilt=0;
+ }
+ if(!isnormal(targettilt2)&&targettilt2){
+ targettilt2=0;
+ }
+
+ //Running velocity
+ //if(!creature==wolftype||targetanimation==rabbitkickanim)
+ if(targetanimation==rabbittackleanim){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*65*scale){
+ velocity/=velspeed;
+ velspeed=speed*65*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }
+ if(targetanimation!=rabbitrunninganim&&targetanimation!=wolfrunninganim){
+ if(isRun()||targetanimation==rabbitkickanim){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*45*scale){
+ velocity/=velspeed;
+ velspeed=speed*45*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ if(velspeed<speed*30*scale)velspeed=speed*30*scale;
+ velocity=flatfacing*velspeed;
+ }
+ }
+ else if(isRun()){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(creature==rabbittype){
+ if(velspeed>speed*55*scale){
+ velocity/=velspeed;
+ velspeed=speed*55*scale;
+ velocity*=velspeed;
+ }
+ }
+ if(creature==wolftype){
+ if(velspeed>speed*75*scale){
+ velocity/=velspeed;
+ velspeed=speed*75*scale;
+ velocity*=velspeed;
+ }
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }
+
+ /*if(creature==wolftype)
+ if(isRun()){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*55*scale){
+ velocity/=velspeed;
+ velspeed=speed*55*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }*/
+
+ if(targetanimation==rollanim&&animation[targetanimation].label[targetframe]!=6){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*45*scale){
+ velocity/=velspeed;
+ velspeed=speed*45*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }
+
+
+ /*if(currentanimation==rollanim&&(isCrouch()||isIdle())){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*25*scale){
+ velocity/=velspeed;
+ velspeed=speed*25*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }*/
+
+ if(targetanimation==sneakanim||targetanimation==walkanim){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*12*scale){
+ velocity/=velspeed;
+ velspeed=speed*12*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }
+
+ if((targetanimation==fightidleanim||targetanimation==knifefightidleanim)&&(currentanimation==bounceidleanim||currentanimation==hurtidleanim)){
+ velocity+=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*2*scale){
+ velocity/=velspeed;
+ velspeed=speed*2*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed;
+ }
+
+
+ if((targetanimation==bounceidleanim||currentanimation==hurtidleanim)&&(currentanimation==fightidleanim||currentanimation==knifefightidleanim)){
+ velocity-=facing*multiplier*speed*700*scale;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*2*scale){
+ velocity/=velspeed;
+ velspeed=speed*2*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed*-1;
+ }
+
+ if(targetanimation==fightsidestep){
+ velocity+=DoRotation(facing*multiplier*speed*700*scale,0,-90,0);
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*12*scale){
+ velocity/=velspeed;
+ velspeed=speed*12*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=DoRotation(flatfacing*velspeed,0,-90,0);
+ }
+
+ if(targetanimation==staggerbackhighanim){
+ coords-=facing*multiplier*speed*16*scale;
+ velocity=0;
+ }
+ if(targetanimation==staggerbackhardanim&&animation[staggerbackhardanim].label[targetframe]!=6){
+ coords-=facing*multiplier*speed*20*scale;
+ velocity=0;
+ }
+
+ if(targetanimation==backhandspringanim){
+ //coords-=facing*multiplier*50*scale;
+ velocity+=facing*multiplier*speed*700*scale*-1;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*50*scale){
+ velocity/=velspeed;
+ velspeed=speed*50*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed*-1;
+ }
+ if(targetanimation==dodgebackanim){
+ //coords-=facing*multiplier*50*scale;
+ velocity+=facing*multiplier*speed*700*scale*-1;
+ velspeed=findLength(&velocity);
+ if(velspeed>speed*60*scale){
+ velocity/=velspeed;
+ velspeed=speed*60*scale;
+ velocity*=velspeed;
+ }
+ velocity.y+=gravity*multiplier*20;
+ ReflectVector(&velocity,&terrain.getNormal(coords.x,coords.z));
+ velspeed=findLength(&velocity);
+ velocity=flatfacing*velspeed*-1;
+ }
+
+ if(targetanimation==jumpupanim||targetanimation==jumpdownanim||isFlip()){
+ velspeed=findLength(&velocity);
+ }
+
+
+ if(targetanimation==jumpupanim||targetanimation==jumpdownanim||isFlip()){
+ velocity.y+=gravity*multiplier;
+ }
+
+ if(targetanimation!=climbanim&&targetanimation!=hanganim&&!isWallJump())coords+=velocity*multiplier;
+
+ if(coords.y<terrain.getHeight(coords.x,coords.z)&&(targetanimation==jumpdownanim||targetanimation==jumpupanim||isFlip())){
+ if(isFlip()&&animation[targetanimation].label[targetframe]==7)RagDoll(0);
+
+ if(targetanimation==jumpupanim){jumppower=-4;targetanimation=getIdle();}
+ target=0;
+ targetframe=0;
+ onterrain=1;
+
+ if(id==0){
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ FSOUND_SetVolume(channels[whooshsound], 0);
+ }
+
+ if(targetanimation==jumpdownanim||isFlip()){
+ if(isFlip())jumppower=-4;
+ targetanimation=getLanding();
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( landsound, samp[landsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound], 128);
+ FSOUND_SetPaused(channels[landsound], FALSE);
+
+ if(id==0){
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ }
+ }
+
+ if(targetanimation!=jumpupanim&&targetanimation!=jumpdownanim&&!isFlip()&&targetanimation!=climbanim&&targetanimation!=hanganim&&!isWallJump())coords.y+=gravity*multiplier*2;
+ if(targetanimation!=jumpupanim&&targetanimation!=jumpdownanim&&!isFlip()&&coords.y<terrain.getHeight(coords.x,coords.z)){
+ coords.y=terrain.getHeight(coords.x,coords.z);
+ onterrain=1;
+ }
+
+
+ if(isIdle()||targetanimation==drawrightanim||targetanimation==drawleftanim||targetanimation==crouchdrawrightanim||targetanimation==crouchstabanim||targetanimation==swordgroundstabanim||isStop()||targetanimation==removeknifeanim||targetanimation==crouchremoveknifeanim||isLanding()||isCrouch()||animation[targetanimation].attack||(targetanimation==rollanim&&animation[targetanimation].label[targetframe]==6)){
+ velspeed=findLength(&velocity);
+ velocity.y=0;
+ if(velspeed<multiplier*300*scale){
+ velocity=0;
+ } else velocity-=velocity/velspeed*multiplier*300*scale;
+ if(velspeed>5&&(isLanding()||isLandhard())){
+ skiddingdelay+=multiplier;
+ if(skiddelay<=0){
+ FootLand(0,.5);
+ FootLand(1,.5);
+ skiddelay=.02;
+ }
+ }
+ else skiddingdelay=0;
+ }
+
+ if(isLandhard()){
+ velspeed=findLength(&velocity);
+ velocity.y=0;
+ if(velspeed<multiplier*600*scale){
+ velocity=0;
+ } else velocity-=velocity/velspeed*multiplier*600*scale;
+ velocity=0;
+ if(velspeed>5&&(isLanding()||isLandhard())){
+ skiddingdelay+=multiplier;
+ if(skiddelay<=0){
+ FootLand(0,.5);
+ FootLand(1,.5);
+ skiddelay=.02;
+ }
+ }
+ else skiddingdelay=0;
+ }
+
+ if(skiddingdelay<0)skiddingdelay+=multiplier;
+ if(skiddingdelay>.02&&!forwardkeydown&&!backkeydown&&!leftkeydown&&!rightkeydown&&!jumpkeydown&&isLanding()&&!landhard){
+ skiddingdelay=-1;
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ if(!onterrain||environment==grassyenvironment){
+ PlaySoundEx( skidsound, samp[skidsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[skidsound], gLoc, vel);
+ FSOUND_SetVolume(channels[skidsound], 128*velspeed/10);
+ FSOUND_SetPaused(channels[skidsound], FALSE);
+ }
+ else {
+ PlaySoundEx( snowskidsound, samp[snowskidsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[snowskidsound], gLoc, vel);
+ FSOUND_SetVolume(channels[snowskidsound], 128*velspeed/10);
+ FSOUND_SetPaused(channels[snowskidsound], FALSE);
+ }
+ }
+
+ if(animation[targetanimation].attack==normalattack&&targetanimation!=rabbitkickanim&&!victim->skeleton.free){
+ terrainnormal=victim->coords-coords;
+ Normalise(&terrainnormal);
+ targetrotation=-asin(0-terrainnormal.x);
+ targetrotation*=360/6.28;
+ if(terrainnormal.z<0)targetrotation=180-targetrotation;
+ targettilt2=-asin(terrainnormal.y)*360/6.28;//*-70;
+ }
+
+ if(animation[targetanimation].attack==reversal&&targetanimation!=rabbittacklinganim){
+ targetrotation=victim->targetrotation;
+ }
+ if(targetanimation==rabbittacklinganim){
+ coords=victim->coords;
+ }
+ }
+ skeleton.oldfree=skeleton.free;
+
+ XYZ midterrain;
+ midterrain=0;
+ midterrain.x=terrain.size*terrain.scale/2;
+ midterrain.z=terrain.size*terrain.scale/2;
+ if(findDistancefastflat(&coords,&midterrain)>(terrain.size*terrain.scale/2-viewdistance)*(terrain.size*terrain.scale/2-viewdistance)){
+ XYZ tempposit;
+ tempposit=coords-midterrain;
+ tempposit.y=0;
+ Normalise(&tempposit);
+ tempposit*=(terrain.size*terrain.scale/2-viewdistance);
+ coords.x=tempposit.x+midterrain.x;
+ coords.z=tempposit.z+midterrain.z;
+ }
+}
+
+int Person::DrawSkeleton(){
+ int oldplayerdetail;
+ if((frustum.SphereInFrustum(coords.x,coords.y+scale*3,coords.z,scale*8)&&findDistancefast(&viewer,&coords)<viewdistance*viewdistance)||skeleton.free==3){
+ if(onterrain&&(isIdle()||isCrouch()||wasIdle()||wasCrouch())&&!skeleton.free){
+ calcrot=1;
+ }
+
+ if(headless){
+ headmorphness=0;
+ headmorphstart=6;
+ headmorphend=6;
+ }
+
+ glAlphaFunc(GL_GREATER, 0.0001);
+ XYZ terrainlight;
+ float terrainheight;
+ float distance;
+ if(!isnormal(rotation))rotation=0;
+ if(!isnormal(tilt))tilt=0;
+ if(!isnormal(tilt2))tilt2=0;
+ oldplayerdetail=playerdetail;
+ playerdetail=0;
+ if(findDistancefast(&viewer,&coords)<viewdistance*viewdistance/32&&detail==2){
+ playerdetail=1;
+ }
+ if(findDistancefast(&viewer,&coords)<viewdistance*viewdistance/128&&detail==1){
+ playerdetail=1;
+ }
+ if(findDistancefast(&viewer,&coords)<viewdistance*viewdistance/256&&(detail!=1&&detail!=2)){
+ playerdetail=1;
+ }
+ if(id==0)playerdetail=1;
+ if(playerdetail!=oldplayerdetail)updatedelay=0;
+ if(playerdetail!=oldplayerdetail)normalsupdatedelay=0;
+ static float updatedelaychange;
+ static float morphness;
+ static float framemult;
+ if(calcrot){
+ skeleton.FindForwards();
+ if(howactive==typesittingwall){
+ skeleton.specialforward[1]=0;
+ skeleton.specialforward[1].z=1;
+ }
+ }
+ static XYZ mid;
+ static float M[16];
+ static int i,j,k;
+ static int weaponattachmuscle;
+ static int weaponrotatemuscle,weaponrotatemuscle2;
+ static XYZ weaponpoint;
+ static int start,endthing;
+ if((dead!=2||skeleton.free!=2)&&updatedelay<=0){
+ if(!isSleeping()&&!isSitting()){
+ if(onterrain&&((isIdle()||isCrouch()||isLanding()||isLandhard()||targetanimation==drawrightanim||targetanimation==drawleftanim||targetanimation==crouchdrawrightanim)&&(wasIdle()||wasCrouch()||wasLanding()||wasLandhard()||currentanimation==drawrightanim||currentanimation==drawleftanim||currentanimation==crouchdrawrightanim))&&!skeleton.free){
+ XYZ point,newpoint,change,change2;
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0);
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0);
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+
+ if(creature==wolftype){
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0);
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0);
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+ }
+ }
+ if(onterrain&&((isIdle()||isCrouch()||isLanding()||isLandhard()||targetanimation==drawrightanim||targetanimation==drawleftanim||targetanimation==crouchdrawrightanim)&&!(wasIdle()||wasCrouch()||wasLanding()||wasLandhard()||currentanimation==drawrightanim||currentanimation==drawleftanim||currentanimation==crouchdrawrightanim))&&!skeleton.free){
+ XYZ point,newpoint,change,change2;
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*target+skeleton.joints[skeleton.jointlabels[leftfoot]].position*(1-target);
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*target+skeleton.joints[skeleton.jointlabels[rightfoot]].position*(1-target);
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+
+ if(creature==wolftype){
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*target+skeleton.joints[skeleton.jointlabels[leftfoot]].position*(1-target);
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*target+skeleton.joints[skeleton.jointlabels[rightfoot]].position*(1-target);
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+ }
+ }
+
+ if(onterrain&&(!(isIdle()||isCrouch()||isLanding()||isLandhard()||targetanimation==drawrightanim||targetanimation==drawleftanim||targetanimation==crouchdrawrightanim)&&(wasIdle()||wasCrouch()||wasLanding()||wasLandhard()||currentanimation==drawrightanim||currentanimation==drawleftanim||currentanimation==crouchdrawrightanim))&&!skeleton.free){
+ XYZ point,newpoint,change,change2;
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*(1-target)+skeleton.joints[skeleton.jointlabels[leftfoot]].position*target;
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*(1-target)+skeleton.joints[skeleton.jointlabels[rightfoot]].position*target;
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+
+ if(creature==wolftype){
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[leftfoot]].position,0,rotation,0)*scale+coords;
+ heightleft=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightleft;
+ change=skeleton.joints[skeleton.jointlabels[leftankle]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[leftknee]].position-skeleton.joints[skeleton.jointlabels[leftfoot]].position;
+ skeleton.joints[skeleton.jointlabels[leftfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*(1-target)+skeleton.joints[skeleton.jointlabels[leftfoot]].position*target;
+ skeleton.joints[skeleton.jointlabels[leftankle]].position=skeleton.joints[skeleton.jointlabels[leftfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[leftknee]].position=(skeleton.joints[skeleton.jointlabels[leftfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[leftknee]].position)/2;
+
+ point=DoRotation(skeleton.joints[skeleton.jointlabels[rightfoot]].position,0,rotation,0)*scale+coords;
+ heightright=terrain.getHeight(point.x,point.z)+.04;
+ point.y=heightright;
+ change=skeleton.joints[skeleton.jointlabels[rightankle]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ change2=skeleton.joints[skeleton.jointlabels[rightknee]].position-skeleton.joints[skeleton.jointlabels[rightfoot]].position;
+ skeleton.joints[skeleton.jointlabels[rightfoot]].position=DoRotation((point-coords)/scale,0,-rotation,0)*(1-target)+skeleton.joints[skeleton.jointlabels[rightfoot]].position*target;
+ skeleton.joints[skeleton.jointlabels[rightankle]].position=skeleton.joints[skeleton.jointlabels[rightfoot]].position+change;
+ skeleton.joints[skeleton.jointlabels[rightknee]].position=(skeleton.joints[skeleton.jointlabels[rightfoot]].position+change2)/2+(skeleton.joints[skeleton.jointlabels[rightknee]].position)/2;
+ skeleton.DoConstraints(&coords,&scale);
+ }
+ }
+ }
+ if(!skeleton.free&&(!animation[targetanimation].attack&&targetanimation!=getupfrombackanim&&targetanimation!=getupfrombackanim&&((targetanimation!=rollanim&&!isFlip())||animation[targetanimation].label[targetframe]==6)&&targetanimation!=getupfromfrontanim&&targetanimation!=wolfrunninganim&&targetanimation!=rabbitrunninganim&&targetanimation!=backhandspringanim&&targetanimation!=walljumpfrontanim&&targetanimation!=hurtidleanim&&!isLandhard()&&!isSleeping()))DoHead();
+ else {
+ targetheadrotation=-targetrotation;
+ targetheadrotation2=0;
+ if(animation[targetanimation].attack==3)targetheadrotation+=180;
+ }
+ for(i=0;i<skeleton.drawmodel.vertexNum;i++){
+ skeleton.drawmodel.vertex[i]=0;
+ skeleton.drawmodel.vertex[i].y=999;
+ }
+ for(i=0;i<skeleton.drawmodellow.vertexNum;i++){
+ skeleton.drawmodellow.vertex[i]=0;
+ skeleton.drawmodellow.vertex[i].y=999;
+ }
+ for(i=0;i<skeleton.drawmodelclothes.vertexNum;i++){
+ skeleton.drawmodelclothes.vertex[i]=0;
+ skeleton.drawmodelclothes.vertex[i].y=999;
+ }
+ for(i=0;i<skeleton.num_muscles;i++){
+ if((skeleton.muscles[i].numvertices>0&&playerdetail)||(skeleton.muscles[i].numverticeslow>0&&!playerdetail)){
+ morphness=0;
+ start=0;
+ endthing=0;
+ if(skeleton.muscles[i].parent1->label==righthand||skeleton.muscles[i].parent2->label==righthand){
+ morphness=righthandmorphness;
+ start=righthandmorphstart;
+ endthing=righthandmorphend;
+ }
+ if(skeleton.muscles[i].parent1->label==lefthand||skeleton.muscles[i].parent2->label==lefthand){
+ morphness=lefthandmorphness;
+ start=lefthandmorphstart;
+ endthing=lefthandmorphend;
+ }
+ if(skeleton.muscles[i].parent1->label==head||skeleton.muscles[i].parent2->label==head){
+ morphness=headmorphness;
+ start=headmorphstart;
+ endthing=headmorphend;
+ }
+ if((skeleton.muscles[i].parent1->label==neck&&skeleton.muscles[i].parent2->label==abdomen)||(skeleton.muscles[i].parent2->label==neck&&skeleton.muscles[i].parent1->label==abdomen)){
+ morphness=chestmorphness;
+ start=chestmorphstart;
+ endthing=chestmorphend;
+ }
+ if((skeleton.muscles[i].parent1->label==groin&&skeleton.muscles[i].parent2->label==abdomen)||(skeleton.muscles[i].parent2->label==groin&&skeleton.muscles[i].parent1->label==abdomen)){
+ morphness=tailmorphness;
+ start=tailmorphstart;
+ endthing=tailmorphend;
+ }
+ if(calcrot)skeleton.FindRotationMuscle(i,targetanimation);
+ mid=(skeleton.muscles[i].parent1->position+skeleton.muscles[i].parent2->position)/2;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ if(!skeleton.free)glRotatef(tilt2,1,0,0);
+ if(!skeleton.free)glRotatef(tilt,0,0,1);
+
+
+ glTranslatef(mid.x,mid.y,mid.z);
+
+ skeleton.muscles[i].lastrotate1=skeleton.muscles[i].rotate1;
+ glRotatef(-skeleton.muscles[i].lastrotate1+90,0,1,0);
+
+ skeleton.muscles[i].lastrotate2=skeleton.muscles[i].rotate2;
+ glRotatef(-skeleton.muscles[i].lastrotate2+90,0,0,1);
+
+ skeleton.muscles[i].lastrotate3=skeleton.muscles[i].rotate3;
+ glRotatef(-skeleton.muscles[i].lastrotate3,0,1,0);
+ /*
+ if(!isnormal(proportionbody.x)||!isnormal(proportionbody.y)||!isnormal(proportionbody.z)){
+ proportionbody=1;
+ proportionweird=1;
+ }
+ if(!isnormal(proportionarms.x)||!isnormal(proportionarms.y)||!isnormal(proportionarms.z)){
+ proportionarms=1;
+ proportionweird=1;
+ }
+ if(!isnormal(proportionhead.x)||!isnormal(proportionhead.y)||!isnormal(proportionhead.z)){
+ proportionhead=1;
+ proportionweird=1;
+ }
+ if(!isnormal(proportionlegs.x)||!isnormal(proportionlegs.y)||!isnormal(proportionlegs.z)){
+ proportionlegs=1;
+ proportionweird=1;
+ }*/
+
+ if(playerdetail||skeleton.free==3)
+ {
+ for(j=0;j<skeleton.muscles[i].numvertices;j++)
+ {
+ /*if(!isnormal(skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x))vertexweird[0]=1;
+ if(!isnormal(skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y))vertexweird[1]=1;
+ if(!isnormal(skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z))vertexweird[2]=1;
+ if(!isnormal(skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x))vertexweird[3]=1;
+ if(!isnormal(skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y))vertexweird[4]=1;
+ if(!isnormal(skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z))vertexweird[5]=1;
+ if(skeleton.muscles[i].vertices[j]<skeleton.model[start].vertexNum&&skeleton.muscles[i].vertices[j]>=0){*/
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(skeleton.muscles[i].parent1->label==abdomen||skeleton.muscles[i].parent2->label==abdomen)
+ glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x*morphness)*proportionbody.x,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y*morphness)*proportionbody.y,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z*morphness)*proportionbody.z);
+ if(skeleton.muscles[i].parent1->label==lefthand||skeleton.muscles[i].parent1->label==righthand||skeleton.muscles[i].parent1->label==leftwrist||skeleton.muscles[i].parent1->label==rightwrist||skeleton.muscles[i].parent1->label==leftelbow||skeleton.muscles[i].parent1->label==rightelbow||skeleton.muscles[i].parent2->label==leftelbow||skeleton.muscles[i].parent2->label==rightelbow)
+ glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x*morphness)*proportionarms.x,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y*morphness)*proportionarms.y,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z*morphness)*proportionarms.z);
+ if(skeleton.muscles[i].parent1->label==leftfoot||skeleton.muscles[i].parent1->label==rightfoot||skeleton.muscles[i].parent1->label==leftankle||skeleton.muscles[i].parent1->label==rightankle||skeleton.muscles[i].parent1->label==leftknee||skeleton.muscles[i].parent1->label==rightknee||skeleton.muscles[i].parent2->label==leftknee||skeleton.muscles[i].parent2->label==rightknee)
+ glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x*morphness)*proportionlegs.x,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y*morphness)*proportionlegs.y,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z*morphness)*proportionlegs.z);
+ if(skeleton.muscles[i].parent1->label==head||skeleton.muscles[i].parent2->label==head)
+ glTranslatef((skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].x*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].x*morphness)*proportionhead.x,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].y*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].y*morphness)*proportionhead.y,
+ (skeleton.model[start].vertex[skeleton.muscles[i].vertices[j]].z*(1-morphness)+skeleton.model[endthing].vertex[skeleton.muscles[i].vertices[j]].z*morphness)*proportionhead.z);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ //if(!isnormal(M[12])||!isnormal(M[13])||!isnormal(M[14]))test=0;
+ //if(isnormal(M[12])&&isnormal(M[13])&&isnormal(M[14])){
+ //if(!isnormal(scale))test=1;
+ //if(isnormal(scale)){
+ skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].x=M[12]*scale;
+ skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].y=M[13]*scale;
+ skeleton.drawmodel.vertex[skeleton.muscles[i].vertices[j]].z=M[14]*scale;
+ //test=2;
+ //}
+ //}
+ glPopMatrix();
+ //}
+ }
+ }
+ if(!playerdetail||skeleton.free==3)
+ {
+ for(j=0;j<skeleton.muscles[i].numverticeslow;j++)
+ {
+ //if(skeleton.muscles[i].verticeslow[j]<skeleton.modellow.vertexNum&&skeleton.muscles[i].verticeslow[j]>=0){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(skeleton.muscles[i].parent1->label==abdomen||skeleton.muscles[i].parent2->label==abdomen)
+ glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionbody.x,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionbody.y,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionbody.z);
+ if(skeleton.muscles[i].parent1->label==lefthand||skeleton.muscles[i].parent1->label==righthand||skeleton.muscles[i].parent1->label==leftwrist||skeleton.muscles[i].parent1->label==rightwrist||skeleton.muscles[i].parent1->label==leftelbow||skeleton.muscles[i].parent1->label==rightelbow||skeleton.muscles[i].parent2->label==leftelbow||skeleton.muscles[i].parent2->label==rightelbow)
+ glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionarms.x,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionarms.y,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionarms.z);
+ if(skeleton.muscles[i].parent1->label==leftfoot||skeleton.muscles[i].parent1->label==rightfoot||skeleton.muscles[i].parent1->label==leftankle||skeleton.muscles[i].parent1->label==rightankle||skeleton.muscles[i].parent1->label==leftknee||skeleton.muscles[i].parent1->label==rightknee||skeleton.muscles[i].parent2->label==leftknee||skeleton.muscles[i].parent2->label==rightknee)
+ glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionlegs.x,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionlegs.y,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionlegs.z);
+ if(skeleton.muscles[i].parent1->label==head||skeleton.muscles[i].parent2->label==head)
+ glTranslatef((skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].x)*proportionhead.x,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].y)*proportionhead.y,
+ (skeleton.modellow.vertex[skeleton.muscles[i].verticeslow[j]].z)*proportionhead.z);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].x=M[12]*scale;
+ skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].y=M[13]*scale;
+ skeleton.drawmodellow.vertex[skeleton.muscles[i].verticeslow[j]].z=M[14]*scale;
+ glPopMatrix();
+ //}
+ }
+ }
+ glPopMatrix();
+ }
+ if(skeleton.clothes&&skeleton.muscles[i].numverticesclothes>0){
+ mid=(skeleton.muscles[i].parent1->position+skeleton.muscles[i].parent2->position)/2;
+
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ if(!skeleton.free)glRotatef(tilt2,1,0,0);
+ if(!skeleton.free)glRotatef(tilt,0,0,1);
+ glTranslatef(mid.x,mid.y,mid.z);
+ skeleton.muscles[i].lastrotate1=skeleton.muscles[i].rotate1;
+ glRotatef(-skeleton.muscles[i].lastrotate1+90,0,1,0);
+
+ skeleton.muscles[i].lastrotate2=skeleton.muscles[i].rotate2;
+ glRotatef(-skeleton.muscles[i].lastrotate2+90,0,0,1);
+
+ skeleton.muscles[i].lastrotate3=skeleton.muscles[i].rotate3;
+ glRotatef(-skeleton.muscles[i].lastrotate3,0,1,0);
+
+ for(j=0;j<skeleton.muscles[i].numverticesclothes;j++){
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(skeleton.muscles[i].parent1->label==abdomen||skeleton.muscles[i].parent2->label==abdomen)
+ glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionbody.x,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionbody.y,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionbody.z);
+ if(skeleton.muscles[i].parent1->label==lefthand||skeleton.muscles[i].parent1->label==righthand||skeleton.muscles[i].parent1->label==leftwrist||skeleton.muscles[i].parent1->label==rightwrist||skeleton.muscles[i].parent1->label==leftelbow||skeleton.muscles[i].parent1->label==rightelbow||skeleton.muscles[i].parent2->label==leftelbow||skeleton.muscles[i].parent2->label==rightelbow)
+ glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionarms.x,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionarms.y,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionarms.z);
+ if(skeleton.muscles[i].parent1->label==leftfoot||skeleton.muscles[i].parent1->label==rightfoot||skeleton.muscles[i].parent1->label==leftankle||skeleton.muscles[i].parent1->label==rightankle||skeleton.muscles[i].parent1->label==leftknee||skeleton.muscles[i].parent1->label==rightknee||skeleton.muscles[i].parent2->label==leftknee||skeleton.muscles[i].parent2->label==rightknee)
+ glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionlegs.x,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionlegs.y,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionlegs.z);
+ if(skeleton.muscles[i].parent1->label==head||skeleton.muscles[i].parent2->label==head)
+ glTranslatef((skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x)*proportionhead.x,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y)*proportionhead.y,
+ (skeleton.modelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z)*proportionhead.z);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].x=M[12]*scale;
+ skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].y=M[13]*scale;
+ skeleton.drawmodelclothes.vertex[skeleton.muscles[i].verticesclothes[j]].z=M[14]*scale;
+ glPopMatrix();
+ }
+ glPopMatrix();
+ }
+ updatedelay=1+(float)(Random()%100)/1000;
+ }
+ if(skeleton.free!=2&&(skeleton.free==1||skeleton.free==3||id==0||(normalsupdatedelay<=0)||targetanimation==getupfromfrontanim||targetanimation==getupfrombackanim||currentanimation==getupfromfrontanim||currentanimation==getupfrombackanim)){
+ normalsupdatedelay=1;
+ if(playerdetail||skeleton.free==3)skeleton.drawmodel.CalculateNormals(0);
+ if(!playerdetail||skeleton.free==3)skeleton.drawmodellow.CalculateNormals(0);
+ if(skeleton.clothes)skeleton.drawmodelclothes.CalculateNormals(0);
+ }
+ else
+ {
+ if(playerdetail||skeleton.free==3)skeleton.drawmodel.UpdateVertexArrayNoTexNoNorm();
+ if(!playerdetail||skeleton.free==3)skeleton.drawmodellow.UpdateVertexArrayNoTexNoNorm();
+ if(skeleton.clothes){
+ skeleton.drawmodelclothes.UpdateVertexArrayNoTexNoNorm();
+ }
+ }
+ }
+ framemult=.01;
+ updatedelaychange=-framemult*4*(45-findDistance(&viewer,&coords)*1);
+ if(updatedelaychange>-realmultiplier*30)updatedelaychange=-realmultiplier*30;
+ if(updatedelaychange>-framemult*4)updatedelaychange=-framemult*4;
+ if(skeleton.free==1)updatedelaychange*=6;
+ if(id==0)updatedelaychange*=8;
+ updatedelay+=updatedelaychange;
+
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(!skeleton.free)glTranslatef(coords.x,coords.y-.02,coords.z);
+ if(skeleton.free)glTranslatef(coords.x,coords.y-.02,coords.z);
+ if(!skeleton.free)glTranslatef(offset.x*scale,offset.y*scale,offset.z*scale);
+ if(!skeleton.free)glRotatef(rotation,0,1,0);
+ if(showpoints){
+ glPointSize(5);
+ glColor4f(.4,1,.4,1);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glBegin(GL_POINTS);
+ if(playerdetail)
+ for(i=0;i<skeleton.drawmodel.vertexNum;i++){
+ glVertex3f(skeleton.drawmodel.vertex[i].x,skeleton.drawmodel.vertex[i].y,skeleton.drawmodel.vertex[i].z);
+ }
+ glEnd();
+ glBegin(GL_LINES);
+
+ if(playerdetail)
+ for(i=0;i<skeleton.drawmodel.TriangleNum;i++){
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[1]].z);
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[2]].z);
+ glVertex3f(skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].x,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].y,skeleton.drawmodel.vertex[skeleton.drawmodel.Triangles[i].vertex[0]].z);
+ }
+
+ glEnd();
+ }
+
+ terrainlight=terrain.getLighting(coords.x,coords.z);
+ distance=findDistancefast(&viewer,&coords);
+ distance=(viewdistance*viewdistance-(distance-(viewdistance*viewdistance*fadestart))*(1/(1-fadestart)))/viewdistance/viewdistance;
+ if(distance>1)distance=1;
+ if(distance>0){
+ terrainheight=(coords.y-terrain.getHeight(coords.x,coords.z))/3+1;
+ if(terrainheight<1)terrainheight=1;
+ if(terrainheight>1.7)terrainheight=1.7;
+
+ //burnt=0;
+ glColor4f((1-(1-terrainlight.x)/terrainheight)-burnt,(1-(1-terrainlight.y)/terrainheight)-burnt,(1-(1-terrainlight.z)/terrainheight)-burnt,distance);
+ glDisable(GL_BLEND);
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glEnable(GL_TEXTURE_2D);
+ if(cellophane){
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(.7,.35,0,.5);
+ glDepthMask(0);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ }
+ if(tutoriallevel&&id!=0){
+ //glDisable(GL_TEXTURE_2D);
+ glColor4f(.7,.7,.7,0.6);
+ glDepthMask(0);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ if(canattack&&cananger)
+ if(animation[targetanimation].attack==normalattack||animation[targetanimation].attack==reversed){
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(1,0,0,0.8);
+ }
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glTranslatef(0,-smoketex,0);
+ glTranslatef(-smoketex,0,0);
+ }
+ if(playerdetail){
+ if(!showpoints){
+ if((tutoriallevel&&id!=0))skeleton.drawmodel.drawdifftex(sprites.cloudimpacttexture);
+ else skeleton.drawmodel.draw();
+ }
+ }
+ if(!playerdetail){
+ if((tutoriallevel&&id!=0))skeleton.drawmodellow.drawdifftex(sprites.cloudimpacttexture);
+ else skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
+ }
+
+ if(!(animation[targetanimation].attack==normalattack||animation[targetanimation].attack==reversed))
+ if(tutoriallevel&&id!=0){
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(.7,.7,.7,0.6);
+ glDepthMask(0);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ if(canattack&&cananger)
+ if(animation[targetanimation].attack==normalattack||animation[targetanimation].attack==reversed){
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(1,0,0,0.8);
+ }
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glTranslatef(0,-smoketex*.6,0);
+ glTranslatef(smoketex*.6,0,0);
+ if(playerdetail){
+ if(!showpoints){
+ if((tutoriallevel&&id!=0))skeleton.drawmodel.drawdifftex(sprites.cloudimpacttexture);
+ else skeleton.drawmodel.draw();
+ }
+ }
+ if(!playerdetail){
+ if((tutoriallevel&&id!=0))skeleton.drawmodellow.drawdifftex(sprites.cloudimpacttexture);
+ else skeleton.drawmodellow.drawdifftex(skeleton.drawmodel.textureptr);
+ }
+ }
+
+
+ if(tutoriallevel&&id!=0){
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glEnable(GL_TEXTURE_2D);
+ }
+ if(skeleton.clothes){
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ if(!immediate)skeleton.drawmodelclothes.draw();
+ if(immediate)skeleton.drawmodelclothes.drawimmediate();
+ glDepthMask(1);
+ }
+ }
+ glPopMatrix();
+
+ if(num_weapons>0){
+ for(k=0;k<num_weapons;k++){
+ i=weaponids[k];
+ if(weaponactive==k){
+ if(weapons.type[i]!=staff){
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==righthand||skeleton.muscles[j].parent2->label==righthand)&&skeleton.muscles[j].numvertices>0){
+ weaponattachmuscle=j;
+ }
+ }
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==rightwrist||skeleton.muscles[j].parent2->label==rightwrist)&&(skeleton.muscles[j].parent1->label!=righthand&&skeleton.muscles[j].parent2->label!=righthand)&&skeleton.muscles[j].numvertices>0){
+ weaponrotatemuscle=j;
+ }
+ }
+ weaponpoint=(skeleton.muscles[weaponattachmuscle].parent1->position+skeleton.muscles[weaponattachmuscle].parent2->position)/2;
+ if(creature==wolftype)weaponpoint=(skeleton.joints[skeleton.jointlabels[rightwrist]].position*.7+skeleton.joints[skeleton.jointlabels[righthand]].position*.3);
+ }
+ if(weapons.type[i]==staff){
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==righthand||skeleton.muscles[j].parent2->label==righthand)&&skeleton.muscles[j].numvertices>0){
+ weaponattachmuscle=j;
+ }
+ }
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==rightelbow||skeleton.muscles[j].parent2->label==rightelbow)&&(skeleton.muscles[j].parent1->label!=rightshoulder&&skeleton.muscles[j].parent2->label!=rightshoulder)&&skeleton.muscles[j].numvertices>0){
+ weaponrotatemuscle=j;
+ }
+ }
+ //weaponpoint=skeleton.joints[skeleton.jointlabels[rightwrist]].position;
+ weaponpoint=(skeleton.muscles[weaponattachmuscle].parent1->position+skeleton.muscles[weaponattachmuscle].parent2->position)/2;
+ //weaponpoint+=skeleton.specialforward[1]*.1+(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightelbow]].position);
+ XYZ tempnormthing,vec1,vec2;
+ vec1=(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightelbow]].position);
+ vec2=(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightshoulder]].position);
+ CrossProduct(&vec1,&vec2,&tempnormthing);
+ Normalise(&tempnormthing);
+ if(targetanimation!=staffhitanim&¤tanimation!=staffhitanim&&targetanimation!=staffgroundsmashanim&¤tanimation!=staffgroundsmashanim&&targetanimation!=staffspinhitanim&¤tanimation!=staffspinhitanim)weaponpoint+=tempnormthing*.1-skeleton.specialforward[1]*.3+(skeleton.joints[skeleton.jointlabels[rightwrist]].position-skeleton.joints[skeleton.jointlabels[rightelbow]].position);
+ /*if(targetanimation==staffhitanim||currentanimation==staffhitanim){
+ XYZ weaptargnorm;
+ weaptargnorm=DoRotation(weapons.tippoint[i]-weapons.position[i],0,-rotation,0);
+ //weaptargnorm=animation[currentanimation].weapontarget[currentframe]*(1-target)+animation[targetanimation].weapontarget[targetframe]*(target);
+ Normalise(&weaptargnorm);
+ weaponpoint-=weaptargnorm*2;
+ }*/
+ }
+ }
+ if(weaponactive!=k&&weaponstuck!=k){
+ if(weapons.type[i]==knife)weaponpoint=skeleton.joints[skeleton.jointlabels[abdomen]].position+(skeleton.joints[skeleton.jointlabels[righthip]].position-skeleton.joints[skeleton.jointlabels[lefthip]].position)*.1+(skeleton.joints[skeleton.jointlabels[rightshoulder]].position-skeleton.joints[skeleton.jointlabels[leftshoulder]].position)*.35;
+ if(weapons.type[i]==sword)weaponpoint=skeleton.joints[skeleton.jointlabels[abdomen]].position+(skeleton.joints[skeleton.jointlabels[lefthip]].position-skeleton.joints[skeleton.jointlabels[righthip]].position)*.09+(skeleton.joints[skeleton.jointlabels[leftshoulder]].position-skeleton.joints[skeleton.jointlabels[rightshoulder]].position)*.33;
+ if(weapons.type[i]==staff)weaponpoint=skeleton.joints[skeleton.jointlabels[abdomen]].position+(skeleton.joints[skeleton.jointlabels[lefthip]].position-skeleton.joints[skeleton.jointlabels[righthip]].position)*.09+(skeleton.joints[skeleton.jointlabels[leftshoulder]].position-skeleton.joints[skeleton.jointlabels[rightshoulder]].position)*.33;
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==abdomen||skeleton.muscles[j].parent2->label==abdomen)&&(skeleton.muscles[j].parent1->label==neck||skeleton.muscles[j].parent2->label==neck)&&skeleton.muscles[j].numvertices>0){
+ weaponrotatemuscle=j;
+ }
+ }
+ }
+ if(weaponstuck==k){
+ if(weaponstuckwhere==0)weaponpoint=skeleton.joints[skeleton.jointlabels[abdomen]].position*.5+skeleton.joints[skeleton.jointlabels[neck]].position*.5-skeleton.forward*.8;
+ else weaponpoint=skeleton.joints[skeleton.jointlabels[abdomen]].position*.5+skeleton.joints[skeleton.jointlabels[neck]].position*.5+skeleton.forward*.8;
+ for(j=0;j<skeleton.num_muscles;j++){
+ if((skeleton.muscles[j].parent1->label==abdomen||skeleton.muscles[j].parent2->label==abdomen)&&(skeleton.muscles[j].parent1->label==neck||skeleton.muscles[j].parent2->label==neck)&&skeleton.muscles[j].numvertices>0){
+ weaponrotatemuscle=j;
+ }
+ }
+ }
+ if(!skeleton.free){
+ weapons.position[i]=DoRotation(DoRotation(DoRotation(weaponpoint,0,0,tilt),tilt2,0,0),0,rotation,0)*scale+coords+currentoffset*(1-target)*scale+targetoffset*target*scale;
+ weapons.bigrotation[i]=rotation;
+ weapons.bigtilt[i]=tilt;
+ weapons.bigtilt2[i]=tilt2;
+ }
+ if(skeleton.free){
+ weapons.position[i]=weaponpoint*scale+coords;
+ weapons.bigrotation[i]=0;
+ weapons.bigtilt[i]=0;
+ weapons.bigtilt2[i]=0;
+ }
+ weapons.rotation1[i]=skeleton.muscles[weaponrotatemuscle].lastrotate1;
+ weapons.rotation2[i]=skeleton.muscles[weaponrotatemuscle].lastrotate2;
+ weapons.rotation3[i]=skeleton.muscles[weaponrotatemuscle].lastrotate3;
+ if(weaponactive==k){
+ if(weapons.type[i]==knife){
+ weapons.smallrotation[i]=180;
+ weapons.smallrotation2[i]=0;
+ if(isCrouch()||wasCrouch()){
+ weapons.smallrotation2[i]=20;
+ }
+ if(targetanimation==hurtidleanim){
+ weapons.smallrotation2[i]=50;
+ }
+ if((currentanimation==crouchstabanim&&targetanimation==crouchstabanim)||(currentanimation==backhandspringanim&&targetanimation==backhandspringanim)){
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=skeleton.joints[skeleton.jointlabels[righthand]].position;
+ temppoint2=animation[currentanimation].weapontarget[currentframe]*(1-target)+animation[targetanimation].weapontarget[targetframe]*(target);
+ distance=findDistance(&temppoint1,&temppoint2);
+ weapons.rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ weapons.rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ weapons.rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ weapons.rotation1[i]*=360/6.28;
+ weapons.rotation3[i]=0;
+ weapons.smallrotation[i]=-90;
+ weapons.smallrotation2[i]=0;
+ if(temppoint1.x>temppoint2.x)weapons.rotation1[i]=360-weapons.rotation1[i];
+ }
+ if((currentanimation==knifeslashreversalanim&&targetanimation==knifeslashreversalanim)||(currentanimation==knifeslashreversedanim&&targetanimation==knifeslashreversedanim)){
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=skeleton.joints[skeleton.jointlabels[righthand]].position;
+ temppoint2=animation[currentanimation].weapontarget[currentframe]*(1-target)+animation[targetanimation].weapontarget[targetframe]*(target);
+ distance=findDistance(&temppoint1,&temppoint2);
+ weapons.rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ weapons.rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ weapons.rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ weapons.rotation1[i]*=360/6.28;
+ weapons.rotation3[i]=0;
+ weapons.smallrotation[i]=90;
+ weapons.smallrotation2[i]=0;
+ if(temppoint1.x>temppoint2.x)weapons.rotation1[i]=360-weapons.rotation1[i];
+ }
+ if(targetanimation==knifethrowanim){
+ weapons.smallrotation[i]=90;
+ //weapons.smallrotation2[i]=-90;
+ weapons.smallrotation2[i]=0;
+ weapons.rotation1[i]=0;
+ weapons.rotation2[i]=0;
+ weapons.rotation3[i]=0;
+ }
+ if(targetanimation==knifesneakattackanim&&targetframe<5){
+ weapons.smallrotation[i]=-90;
+ weapons.rotation1[i]=0;
+ weapons.rotation2[i]=0;
+ weapons.rotation3[i]=0;
+ }
+ }
+ if(weapons.type[i]==sword){
+ weapons.smallrotation[i]=0;
+ weapons.smallrotation2[i]=0;
+ if(targetanimation==knifethrowanim){
+ weapons.smallrotation[i]=-90;
+ weapons.smallrotation2[i]=0;
+ weapons.rotation1[i]=0;
+ weapons.rotation2[i]=0;
+ weapons.rotation3[i]=0;
+ }
+ if((targetanimation==swordgroundstabanim&¤tanimation==swordgroundstabanim)||(targetanimation==swordsneakattackanim&¤tanimation==swordsneakattackanim)||(targetanimation==swordslashparryanim&¤tanimation==swordslashparryanim)||(targetanimation==swordslashparriedanim&¤tanimation==swordslashparriedanim)||(targetanimation==swordslashreversalanim&¤tanimation==swordslashreversalanim)||(targetanimation==swordslashreversedanim&¤tanimation==swordslashreversedanim)||(targetanimation==knifeslashreversalanim&¤tanimation==knifeslashreversalanim)||(targetanimation==knifeslashreversedanim&¤tanimation==knifeslashreversedanim)||(targetanimation==swordslashanim&¤tanimation==swordslashanim)||(targetanimation==drawleftanim&¤tanimation==drawleftanim)||(currentanimation==backhandspringanim&&targetanimation==backhandspringanim)){
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=animation[currentanimation].position[skeleton.jointlabels[righthand]][currentframe]*(1-target)+animation[targetanimation].position[skeleton.jointlabels[righthand]][targetframe]*(target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
+ temppoint2=animation[currentanimation].weapontarget[currentframe]*(1-target)+animation[targetanimation].weapontarget[targetframe]*(target);
+ distance=findDistance(&temppoint1,&temppoint2);
+ weapons.rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ weapons.rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ weapons.rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ weapons.rotation1[i]*=360/6.28;
+ weapons.rotation3[i]=0;
+ weapons.smallrotation[i]=90;
+ weapons.smallrotation2[i]=0;
+ if(temppoint1.x>temppoint2.x)weapons.rotation1[i]=360-weapons.rotation1[i];
+ }
+ }
+ if(weapons.type[i]==staff){
+ weapons.smallrotation[i]=100;
+ weapons.smallrotation2[i]=0;
+ if((targetanimation==staffhitanim&¤tanimation==staffhitanim)||(targetanimation==staffhitreversedanim&¤tanimation==staffhitreversedanim)||(targetanimation==staffspinhitreversedanim&¤tanimation==staffspinhitreversedanim)||(targetanimation==staffgroundsmashanim&¤tanimation==staffgroundsmashanim)||(targetanimation==staffspinhitanim&¤tanimation==staffspinhitanim)){
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=animation[currentanimation].position[skeleton.jointlabels[righthand]][currentframe]*(1-target)+animation[targetanimation].position[skeleton.jointlabels[righthand]][targetframe]*(target); //skeleton.joints[skeleton.jointlabels[righthand]].position;
+ temppoint2=animation[currentanimation].weapontarget[currentframe]*(1-target)+animation[targetanimation].weapontarget[targetframe]*(target);
+ distance=findDistance(&temppoint1,&temppoint2);
+ weapons.rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ weapons.rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ weapons.rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ weapons.rotation1[i]*=360/6.28;
+ weapons.rotation3[i]=0;
+ weapons.smallrotation[i]=90;
+ weapons.smallrotation2[i]=0;
+ if(temppoint1.x>temppoint2.x)weapons.rotation1[i]=360-weapons.rotation1[i];
+ }
+ }
+ }
+ if(weaponactive!=k&&weaponstuck!=k){
+ if(weapons.type[i]==knife){
+ weapons.smallrotation[i]=-70;
+ weapons.smallrotation2[i]=10;
+ }
+ if(weapons.type[i]==sword){
+ weapons.smallrotation[i]=-100;
+ weapons.smallrotation2[i]=-8;
+ }
+ if(weapons.type[i]==staff){
+ weapons.smallrotation[i]=-100;
+ weapons.smallrotation2[i]=-8;
+ }
+ }
+ if(weaponstuck==k){
+ if(weaponstuckwhere==0)weapons.smallrotation[i]=180;
+ else weapons.smallrotation[i]=0;
+ weapons.smallrotation2[i]=10;
+ //if(animation[targetanimation].height==lowheight&&animation[targetanimation].attack==neutral){
+ //}
+ }
+ }
+ }
+ }
+
+ calcrot=0;
+ if(skeleton.free)calcrot=1;
+ if(animation[targetanimation].attack||isRun()||targetanimation==staggerbackhardanim||isFlip()||targetanimation==climbanim||targetanimation==sneakanim||targetanimation==rollanim||targetanimation==walkanim||targetanimation==backhandspringanim||isFlip()||isWallJump())calcrot=1;
+ if(currentanimation!=targetanimation)calcrot=1;
+ //if(id==0)calcrot=1;
+ if(skeleton.free==2)calcrot=0;
+
+ return 0;
+}
+
+
+int Person::SphereCheck(XYZ *p1,float radius, XYZ *p, XYZ *move, float *rotate, Model *model)
+{
+ static int i,j;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+ static XYZ oldp1;
+ static XYZ start,end;
+ static float slopethreshold=-.4;
+
+ firstintersecting=-1;
+
+ oldp1=*p1;
+ *p1=*p1-*move;
+ if(findDistancefast(p1,&model->boundingspherecenter)>radius*radius+model->boundingsphereradius*model->boundingsphereradius)return -1;
+ if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
+ for(i=0;i<4;i++){
+ for (j=0;j<model->TriangleNum;j++){
+ if(model->facenormals[j].y<=slopethreshold){
+ intersecting=0;
+ distance=abs((model->facenormals[j].x*p1->x)+(model->facenormals[j].y*p1->y)+(model->facenormals[j].z*p1->z)-((model->facenormals[j].x*model->vertex[model->Triangles[j].vertex[0]].x)+(model->facenormals[j].y*model->vertex[model->Triangles[j].vertex[0]].y)+(model->facenormals[j].z*model->vertex[model->Triangles[j].vertex[0]].z)));
+ if(distance<radius){
+ point=*p1-model->facenormals[j]*distance;
+ if(PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))intersecting=1;
+ if(!intersecting)intersecting=sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
+ &model->vertex[model->Triangles[j].vertex[1]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[1]],
+ &model->vertex[model->Triangles[j].vertex[2]],
+ p1, &radius);
+ if(!intersecting)intersecting=sphere_line_intersection(&model->vertex[model->Triangles[j].vertex[0]],
+ &model->vertex[model->Triangles[j].vertex[2]],
+ p1, &radius);
+ end=*p1-point;
+ if(dotproduct(&model->facenormals[j],&end)>0&&intersecting){
+ start=*p1;
+ end=*p1;
+ end.y-=radius;
+ if(LineFacetd(&start,&end,&model->vertex[model->Triangles[j].vertex[0]],&model->vertex[model->Triangles[j].vertex[1]],&model->vertex[model->Triangles[j].vertex[2]],&model->facenormals[j],&point)){
+ p1->y=point.y+radius;
+ if((targetanimation==jumpdownanim||isFlip())){
+ if(isFlip()&&(targetframe<5||animation[targetanimation].label[targetframe]==7||animation[targetanimation].label[targetframe]==4))RagDoll(0);
+
+ if(targetanimation==jumpupanim){jumppower=-4;targetanimation=getIdle();}
+ target=0;
+ targetframe=0;
+ onterrain=1;
+
+ if(id==0){
+ FSOUND_SetPaused(channels[whooshsound], TRUE);
+ FSOUND_SetVolume(channels[whooshsound], 0);
+ }
+
+ if((targetanimation==jumpdownanim||isFlip())&&!wasLanding()&&!wasLandhard()){
+ if(isFlip())jumppower=-4;
+ targetanimation=getLanding();
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=coords.x;
+ gLoc[1]=coords.y;
+ gLoc[2]=coords.z;
+ vel[0]=velocity.x;
+ vel[1]=velocity.y;
+ vel[2]=velocity.z;
+ PlaySoundEx( landsound, samp[landsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound], 128);
+ FSOUND_SetPaused(channels[landsound], FALSE);
+
+ if(id==0){
+ envsound[numenvsounds]=coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ }
+ }
+ }
+ }
+ }
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+ }
+ }
+ for (j=0;j<model->TriangleNum;j++){
+ if(model->facenormals[j].y>slopethreshold){
+ intersecting=0;
+ start=*p1;
+ start.y-=radius/4;
+ distance=abs((model->facenormals[j].x*start.x)+(model->facenormals[j].y*start.y)+(model->facenormals[j].z*start.z)-((model->facenormals[j].x*model->vertex[model->Triangles[j].vertex[0]].x)+(model->facenormals[j].y*model->vertex[model->Triangles[j].vertex[0]].y)+(model->facenormals[j].z*model->vertex[model->Triangles[j].vertex[0]].z)));
+ if(distance<radius*.5){
+ point=start-model->facenormals[j]*distance;
+ if(PointInTriangle( &point, model->facenormals[j], &model->vertex[model->Triangles[j].vertex[0]], &model->vertex[model->Triangles[j].vertex[1]], &model->vertex[model->Triangles[j].vertex[2]]))intersecting=1;
+ if(!intersecting)intersecting=sphere_line_intersection(model->vertex[model->Triangles[j].vertex[0]].x,model->vertex[model->Triangles[j].vertex[0]].y,model->vertex[model->Triangles[j].vertex[0]].z,
+ model->vertex[model->Triangles[j].vertex[1]].x,model->vertex[model->Triangles[j].vertex[1]].y,model->vertex[model->Triangles[j].vertex[1]].z,
+ p1->x, p1->y, p1->z, radius/2);
+ if(!intersecting)intersecting=sphere_line_intersection(model->vertex[model->Triangles[j].vertex[1]].x,model->vertex[model->Triangles[j].vertex[1]].y,model->vertex[model->Triangles[j].vertex[1]].z,
+ model->vertex[model->Triangles[j].vertex[2]].x,model->vertex[model->Triangles[j].vertex[2]].y,model->vertex[model->Triangles[j].vertex[2]].z,
+ p1->x, p1->y, p1->z, radius/2);
+ if(!intersecting)intersecting=sphere_line_intersection(model->vertex[model->Triangles[j].vertex[0]].x,model->vertex[model->Triangles[j].vertex[0]].y,model->vertex[model->Triangles[j].vertex[0]].z,
+ model->vertex[model->Triangles[j].vertex[2]].x,model->vertex[model->Triangles[j].vertex[2]].y,model->vertex[model->Triangles[j].vertex[2]].z,
+ p1->x, p1->y, p1->z, radius/2);
+ end=*p1-point;
+ if(dotproduct(&model->facenormals[j],&end)>0&&intersecting){
+ if((targetanimation==jumpdownanim||targetanimation==jumpupanim||isFlip())){
+ start=velocity;
+ velocity-=DoRotation(model->facenormals[j],0,*rotate,0)*findLength(&velocity)*abs(normaldotproduct(velocity,DoRotation(model->facenormals[j],0,*rotate,0)));//(distance-radius*.5)/multiplier;
+ if(findLengthfast(&start)<findLengthfast(&velocity))velocity=start;
+ }
+ *p1+=model->facenormals[j]*(distance-radius*.5);
+ }
+ }
+ if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+ }
+ }
+ }
+ if(*rotate)*p=DoRotation(*p,0,*rotate,0);
+ *p=*p+*move;
+ if(*rotate)*p1=DoRotation(*p1,0,*rotate,0);
+ *p1+=*move;
+ return firstintersecting;
+}
+
+Person::Person()
+{
+ whichpatchx = 0;
+ whichpatchz = 0;
+
+ currentframe = 0;
+ targetframe = 0;
+ currentanimation = 0;
+ targetanimation = 0;
+ oldcurrentframe = 0;
+ oldtargetframe = 0;
+ oldcurrentanimation = 0;
+ oldtargetanimation = 0;
+
+ howactive = 0;
+
+ parriedrecently = 0;
+
+ superruntoggle = 0;
+
+ lastattack = 0,lastattack2 = 0,lastattack3 = 0;
+
+ currentoffset = 0,targetoffset = 0,offset = 0;
+ target = 0;
+ transspeed = 0;
+
+ realoldcoords = 0;
+ oldcoords = 0;
+ coords = 0;
+ originalcoords = 0;
+ velocity = 0;
+
+ proportionhead = 0;
+ proportionlegs = 0;
+ proportionarms = 0;
+ proportionbody = 0;
+
+ heightleft = 0;
+ heightright = 0;
+
+ unconscioustime = 0;
+
+ immobile = 0;
+
+ velspeed = 0;
+ targetrotation = 0;
+ targetrot = 0;
+ rot = 0;
+ oldrot = 0;
+ lookrotation = 0;
+ lookrotation2 = 0;
+ rotation = 0;
+ rotation2 = 0;
+ lowrotation = 0;
+ tilt = 0;
+ targettilt = 0;
+ tilt2 = 0;
+ targettilt2 = 0;
+ rabbitkickenabled = 0;
+
+ bloodloss = 0;
+ bleeddelay = 0;
+ skiddelay = 0;
+ skiddingdelay = 0;
+ deathbleeding = 0;
+ tempdeltav = 0;
+
+ damagetolerance = 0;
+ damage = 0;
+ permanentdamage = 0;
+ superpermanentdamage = 0; lastcollide = 0;
+ dead = 0;
+
+ jumppower = 0;
+ onground = 0;
+ madskills = 0;
+
+ wentforweapon = 0;
+
+ calcrot = 0;
+
+ backwardsanim = 0;
+
+ facing = 0;
+
+ bleeding = 0;
+ bleedx = 0,bleedy;
+ direction = 0;
+ texupdatedelay = 0;
+
+ headrotation = 0,headrotation2 = 0;
+ targetheadrotation = 0,targetheadrotation2 = 0;
+
+ onterrain = 0;
+ pause = 0;
+
+ grabdelay = 0;
+
+ victim = 0;
+ hasvictim = 0;
+
+ updatedelay = 0;
+ normalsupdatedelay = 0;
+
+ jumpstart = 0;
+
+ forwardkeydown = 0;
+ forwardstogglekeydown = 0;
+ rightkeydown = 0;
+ leftkeydown = 0;
+ backkeydown = 0;
+ jumpkeydown = 0;
+ jumptogglekeydown = 0;
+ crouchkeydown = 0;
+ crouchtogglekeydown = 0;
+ drawkeydown = 0;
+ drawtogglekeydown = 0;
+ throwkeydown = 0;
+ throwtogglekeydown = 0;
+ attackkeydown = 0;
+ feint = 0;
+ lastfeint = 0;
+ headless = 0;
+
+ crouchkeydowntime = 0;
+ jumpkeydowntime = 0;
+ freefall = 0;
+
+
+ turnspeed = 0;
+
+ aitype = 0;
+ aitarget = 0;
+ aiupdatedelay = 0;
+ losupdatedelay = 0;
+ ally = 0;
+ movetarget = 0;
+ collide = 0;
+ collided = 0;
+ avoidcollided = 0;
+ loaded = 0;
+ whichdirection = 0;
+ whichdirectiondelay = 0;
+ avoidsomething = 0; avoidwhere = 0;
+ blooddimamount = 0;
+
+ staggerdelay = 0;
+ blinkdelay = 0;
+ twitchdelay = 0;
+ twitchdelay2 = 0;
+ twitchdelay3 = 0;
+ lefthandmorphness = 0;
+ righthandmorphness = 0;
+ headmorphness = 0;
+ chestmorphness = 0;
+ tailmorphness = 0;
+ targetlefthandmorphness = 0;
+ targetrighthandmorphness = 0;
+ targetheadmorphness = 0;
+ targetchestmorphness = 0;
+ targettailmorphness = 0;
+ lefthandmorphstart = 0,lefthandmorphend = 0;
+ righthandmorphstart = 0,righthandmorphend = 0;
+ headmorphstart = 0,headmorphend = 0;
+ chestmorphstart = 0,chestmorphend = 0;
+ tailmorphstart = 0,tailmorphend = 0;
+
+ weaponmissdelay = 0;
+ highreversaldelay = 0;
+ lowreversaldelay = 0;
+ nocollidedelay = 0;
+
+ creature = 0;
+
+ id = 0;
+
+ //Skeleton skeleton;
+
+ speed = 0;
+ scale = 0;
+ power = 0;
+ speedmult = 0;
+
+ protectionhead = 0;
+ protectionhigh = 0;
+ protectionlow = 0;
+ armorhead = 0;
+ armorhigh = 0;
+ armorlow = 0;
+ metalhead = 0;
+ metalhigh = 0;
+ metallow = 0;
+
+ numclothes = 0;
+
+ memset(clothes, 0, sizeof(clothes));
+ memset(clothestintr, 0, sizeof(clothestintr));
+ memset(clothestintg, 0, sizeof(clothestintg));
+ memset(clothestintb, 0, sizeof(clothestintb));
+
+ landhard = 0;
+ bled = 0;
+ spurt = 0;
+ onfire = 0;
+ onfiredelay = 0; burnt = 0;
+ fireduration = 0;
+
+ flamedelay = 0;
+ updatestuffdelay = 0;
+
+ playerdetail = 0;
+
+ num_weapons = 0;
+
+ memset(weaponids, 0, sizeof(weaponids));
+
+ weaponactive = 0;
+ weaponstuck = 0;
+ weaponstuckwhere = 0;
+ weaponwhere = 0;
+
+ numwaypoints = 0;
+
+ memset(waypoints, 0, sizeof(waypoints));
+ memset(waypointtype, 0, sizeof(waypointtype));
+
+ pausetime = 0;
+ hastempwaypoint = 0;
+ tempwaypoint = 0;
+
+ headtarget = 0;
+ interestdelay = 0;
+
+ finalfinaltarget = 0;
+ finaltarget = 0;
+ finalpathfindpoint = 0;
+ targetpathfindpoint = 0;
+ lastpathfindpoint = 0;
+ lastpathfindpoint2 = 0;
+ lastpathfindpoint3 = 0;
+ lastpathfindpoint4 = 0;
+ onpath = 0;
+
+ waypoint = 0;
+ jumppath = 0;
+
+ lastseen = 0;
+ lastseentime = 0;
+ lastchecktime = 0;
+ stunned = 0;
+ surprised = 0;
+ runninghowlong = 0; lastoccluded = 0;
+ laststanding = 0;
+ escapednum = 0;
+
+ speechdelay = 0;
+ neckspurtdelay = 0;
+ neckspurtparticledelay = 0;
+ neckspurtamount = 0;
+
+ whichskin = 0;
+ rabbitkickragdoll = 0;
+
+ averageloc = 0;
+ oldaverageloc = 0;
+
+ //Animation tempanimation;
+
+ occluded = 0;
+
+ jumpclimb = 0;
+}
+
+Person::~Person()
+{
+}
--- /dev/null
+#ifndef _PERSON_H_
+#define _PERSON_H_
+
+/**> HEADER FILES <**/
+
+#include "gl.h"
+#include "Quaternions.h"
+#include "fmod.h"
+#include "skeleton.h"
+#include "models.h"
+#include "Constants.h"
+#include "Terrain.h"
+#include "Sprites.h"
+#include <cmath>
+#include "Weapons.h"
+
+#define passivetype 0
+#define guardtype 1
+#define searchtype 2
+#define attacktype 3
+#define attacktypecutoff 4
+#define playercontrolled 5
+#define gethelptype 6
+#define getweapontype 7
+#define pathfindtype 8
+
+#define rabbittype 0
+#define wolftype 1
+
+class HitStruct
+{
+ public:
+ Joint *joint1;
+ Joint *joint2;
+ XYZ hitlocation;
+ bool collision;
+};
+
+class Person
+{
+ public:
+ Person();
+ ~Person();
+
+ int whichpatchx;
+ int whichpatchz;
+
+ int currentframe;
+ int targetframe;
+ int currentanimation;
+ int targetanimation;
+ int oldcurrentframe;
+ int oldtargetframe;
+ int oldcurrentanimation;
+ int oldtargetanimation;
+
+ int howactive;
+
+ float parriedrecently;
+
+ bool superruntoggle;
+
+ int lastattack,lastattack2,lastattack3;
+
+ XYZ currentoffset,targetoffset,offset;
+ float target;
+ float transspeed;
+
+ XYZ realoldcoords;
+ XYZ oldcoords;
+ XYZ coords;
+ XYZ originalcoords;
+ XYZ velocity;
+
+ XYZ proportionhead;
+ XYZ proportionlegs;
+ XYZ proportionarms;
+ XYZ proportionbody;
+
+ float heightleft;
+ float heightright;
+
+ float unconscioustime;
+
+ bool immobile;
+
+ float velspeed;
+ float targetrotation;
+ float targetrot;
+ float rot;
+ float oldrot;
+ float lookrotation;
+ float lookrotation2;
+ float rotation;
+ float rotation2;
+ float lowrotation;
+ float tilt;
+ float targettilt;
+ float tilt2;
+ float targettilt2;
+ bool rabbitkickenabled;
+
+ float bloodloss;
+ float bleeddelay;
+ float skiddelay;
+ float skiddingdelay;
+ float deathbleeding;
+ float tempdeltav;
+
+ float damagetolerance;
+ float damage;
+ float permanentdamage;
+ float superpermanentdamage; float lastcollide;
+ int dead;
+
+ float jumppower;
+ bool onground;
+ int madskills;
+
+ int wentforweapon;
+
+ bool calcrot;
+
+ bool backwardsanim;
+
+ XYZ facing;
+
+ float bleeding;
+ float bleedx,bleedy;
+ int direction;
+ float texupdatedelay;
+
+ float headrotation,headrotation2;
+ float targetheadrotation,targetheadrotation2;
+
+ bool onterrain;
+ bool pause;
+
+ float grabdelay;
+
+ Person *victim;
+ bool hasvictim;
+
+ float updatedelay;
+ float normalsupdatedelay;
+
+ bool jumpstart;
+
+ bool forwardkeydown;
+ bool forwardstogglekeydown;
+ bool rightkeydown;
+ bool leftkeydown;
+ bool backkeydown;
+ bool jumpkeydown;
+ bool jumptogglekeydown;
+ bool crouchkeydown;
+ bool crouchtogglekeydown;
+ bool drawkeydown;
+ bool drawtogglekeydown;
+ bool throwkeydown;
+ bool throwtogglekeydown;
+ bool attackkeydown;
+ bool feint;
+ bool lastfeint;
+ bool headless;
+
+ float crouchkeydowntime;
+ float jumpkeydowntime;
+ bool freefall;
+
+
+ float turnspeed;
+
+ int aitype;
+ int aitarget;
+ float aiupdatedelay;
+ float losupdatedelay;
+ int ally;
+ XYZ movetarget;
+ float collide;
+ float collided;
+ float avoidcollided;
+ bool loaded;
+ bool whichdirection;
+ float whichdirectiondelay;
+ bool avoidsomething; XYZ avoidwhere;
+ float blooddimamount;
+
+ float staggerdelay;
+ float blinkdelay;
+ float twitchdelay;
+ float twitchdelay2;
+ float twitchdelay3;
+ float lefthandmorphness;
+ float righthandmorphness;
+ float headmorphness;
+ float chestmorphness;
+ float tailmorphness;
+ float targetlefthandmorphness;
+ float targetrighthandmorphness;
+ float targetheadmorphness;
+ float targetchestmorphness;
+ float targettailmorphness;
+ int lefthandmorphstart,lefthandmorphend;
+ int righthandmorphstart,righthandmorphend;
+ int headmorphstart,headmorphend;
+ int chestmorphstart,chestmorphend;
+ int tailmorphstart,tailmorphend;
+
+ float weaponmissdelay;
+ float highreversaldelay;
+ float lowreversaldelay;
+ float nocollidedelay;
+
+ int creature;
+
+ int id;
+
+ Skeleton skeleton;
+
+ float speed;
+ float scale;
+ float power;
+ float speedmult;
+
+ float protectionhead;
+ float protectionhigh;
+ float protectionlow;
+ float armorhead;
+ float armorhigh;
+ float armorlow;
+ bool metalhead;
+ bool metalhigh;
+ bool metallow;
+
+ int numclothes;
+ char clothes[10][256];
+ float clothestintr[10];
+ float clothestintg[10];
+ float clothestintb[10];
+
+ bool landhard;
+ bool bled;
+ bool spurt;
+ bool onfire;
+ float onfiredelay; float burnt;
+ float fireduration;
+
+ float flamedelay;
+ float updatestuffdelay;
+
+ int playerdetail;
+
+ int num_weapons;
+ int weaponids[4];
+ int weaponactive;
+ int weaponstuck;
+ int weaponstuckwhere;
+ int weaponwhere;
+
+ int numwaypoints;
+ XYZ waypoints[90];
+ int waypointtype[90];
+ float pausetime;
+ bool hastempwaypoint;
+ XYZ tempwaypoint;
+
+ XYZ headtarget;
+ float interestdelay;
+
+ XYZ finalfinaltarget;
+ XYZ finaltarget;
+ int finalpathfindpoint;
+ int targetpathfindpoint;
+ int lastpathfindpoint;
+ int lastpathfindpoint2;
+ int lastpathfindpoint3;
+ int lastpathfindpoint4;
+ bool onpath;
+
+ int waypoint;
+ bool jumppath;
+
+ XYZ lastseen;
+ float lastseentime;
+ float lastchecktime;
+ float stunned;
+ float surprised;
+ float runninghowlong; int lastoccluded;
+ int laststanding;
+ int escapednum;
+
+ float speechdelay;
+ float neckspurtdelay;
+ float neckspurtparticledelay;
+ float neckspurtamount;
+
+ int whichskin;
+ bool rabbitkickragdoll;
+
+ XYZ averageloc;
+ XYZ oldaverageloc;
+
+ Animation tempanimation;
+
+ float occluded;
+
+ void CheckKick();
+ void CatchFire();
+ void DoBlood(float howmuch, int which);
+ void DoBloodBig(float howmuch, int which);
+ bool DoBloodBigWhere(float howmuch, int which, XYZ where);
+
+ bool wasIdle();
+ bool isIdle();
+ int getIdle();
+
+ bool isSitting();
+ bool isSleeping();
+
+
+ bool wasCrouch();
+ bool isCrouch();
+ int getCrouch();
+
+ bool wasStop();
+ bool isStop();
+ int getStop();
+
+ bool wasSneak();
+ bool isSneak();
+ int getSneak();
+
+ bool wasRun();
+ bool isRun();
+ int getRun();
+
+ bool wasLanding();
+ bool isLanding();
+ int getLanding();
+
+ bool wasLandhard();
+ bool isLandhard();
+ int getLandhard();
+
+ bool isFlip();
+ bool wasFlip();
+
+ bool jumpclimb;
+
+ bool isWallJump();
+ void Reverse();
+ void DoDamage(float howmuch);
+ void DoHead();
+ void DoMipmaps(int howmanylevels, float startx, float endx, float starty, float endy);
+ int SphereCheck(XYZ *p1,float radius, XYZ *p, XYZ *move, float *rotate, Model *model);
+ int DrawSkeleton();
+ void Puff(int whichlabel);
+ void FootLand(int which, float opacity);
+ void DoStuff();
+ void DoAnimations();
+ void RagDoll(bool checkcollision);
+ HitStruct BulletCollideWithPlayer(XYZ start, XYZ end);
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef _PHYSICSMATH_H_
+#define _PHYSICSMATH_H_
+
+//#include <Carbon.h>
+
+#ifdef WIN32
+#include "WinDefs.h"
+#endif
+
+//------------------------------------------------------------------------//
+// Misc. Constants
+//------------------------------------------------------------------------//
+
+float const pi = 3.14159265f;
+float const g = -32.174f; // acceleration due to gravity, ft/s^2
+float const rho = 0.0023769f; // desity of air at sea level, slugs/ft^3
+float const tol = 0.0000000001f; // float type tolerance
+
+
+//------------------------------------------------------------------------//
+// Misc. Functions
+//------------------------------------------------------------------------//
+inline float DegreesToRadians(float deg);
+inline float RadiansToDegrees(float rad);
+
+inline float DegreesToRadians(float deg)
+{
+ return deg * pi / 180.0f;
+}
+
+inline float RadiansToDegrees(float rad)
+{
+ return rad * 180.0f / pi;
+}
+
+//------------------------------------------------------------------------//
+// Vector Class and vector functions
+//------------------------------------------------------------------------//
+class Vector {
+public:
+ float x;
+ float y;
+ float z;
+
+ Vector(void);
+ Vector(float xi, float yi, float zi);
+
+ float Magnitude(void);
+ void Normalize(void);
+ void Reverse(void);
+
+ Vector& operator+=(Vector u); // vector addition
+ Vector& operator-=(Vector u); // vector subtraction
+ Vector& operator*=(float s); // scalar multiply
+ Vector& operator/=(float s); // scalar divide
+
+ Vector operator-(void);
+
+};
+
+inline Vector operator+(Vector u, Vector v);
+inline Vector operator-(Vector u, Vector v);
+inline Vector operator^(Vector u, Vector v);
+inline float operator*(Vector u, Vector v);
+inline Vector operator*(float s, Vector u);
+inline Vector operator*(Vector u, float s);
+inline Vector operator/(Vector u, float s);
+inline float TripleScalarProduct(Vector u, Vector v, Vector w);
+/*
+float fast_sqrt2 (register float arg);
+float fast_sqrt2 (register float arg)
+{
+// Can replace with slower return std::sqrt(arg);
+register float result;
+
+if (arg == 0.0) return 0.0;
+
+asm {
+frsqrte result,arg // Calculate Square root
+}
+
+// Newton Rhapson iterations.
+result = result + 0.5 * result * (1.0 - arg * result * result);
+result = result + 0.5 * result * (1.0 - arg * result * result);
+
+return result * arg;
+}
+*/
+inline Vector::Vector(void)
+{
+ x = 0;
+ y = 0;
+ z = 0;
+}
+
+inline Vector::Vector(float xi, float yi, float zi)
+{
+ x = xi;
+ y = yi;
+ z = zi;
+}
+
+inline float Vector::Magnitude(void)
+{
+ return (float) sqrt(x*x + y*y + z*z);
+}
+
+inline void Vector::Normalize(void)
+{
+ float m = (float) sqrt(x*x + y*y + z*z);
+ if(m <= tol) m = 1;
+ x /= m;
+ y /= m;
+ z /= m;
+
+ if (fabs(x) < tol) x = 0.0f;
+ if (fabs(y) < tol) y = 0.0f;
+ if (fabs(z) < tol) z = 0.0f;
+}
+
+inline void Vector::Reverse(void)
+{
+ x = -x;
+ y = -y;
+ z = -z;
+}
+
+inline Vector& Vector::operator+=(Vector u)
+{
+ x += u.x;
+ y += u.y;
+ z += u.z;
+ return *this;
+}
+
+inline Vector& Vector::operator-=(Vector u)
+{
+ x -= u.x;
+ y -= u.y;
+ z -= u.z;
+ return *this;
+}
+
+inline Vector& Vector::operator*=(float s)
+{
+ x *= s;
+ y *= s;
+ z *= s;
+ return *this;
+}
+
+inline Vector& Vector::operator/=(float s)
+{
+ x /= s;
+ y /= s;
+ z /= s;
+ return *this;
+}
+
+inline Vector Vector::operator-(void)
+{
+ return Vector(-x, -y, -z);
+}
+
+
+inline Vector operator+(Vector u, Vector v)
+{
+ return Vector(u.x + v.x, u.y + v.y, u.z + v.z);
+}
+
+inline Vector operator-(Vector u, Vector v)
+{
+ return Vector(u.x - v.x, u.y - v.y, u.z - v.z);
+}
+
+// Vector cross product (u cross v)
+inline Vector operator^(Vector u, Vector v)
+{
+ return Vector( u.y*v.z - u.z*v.y,
+ -u.x*v.z + u.z*v.x,
+ u.x*v.y - u.y*v.x );
+}
+
+// Vector dot product
+inline float operator*(Vector u, Vector v)
+{
+ return (u.x*v.x + u.y*v.y + u.z*v.z);
+}
+
+inline Vector operator*(float s, Vector u)
+{
+ return Vector(u.x*s, u.y*s, u.z*s);
+}
+
+inline Vector operator*(Vector u, float s)
+{
+ return Vector(u.x*s, u.y*s, u.z*s);
+}
+
+inline Vector operator/(Vector u, float s)
+{
+ return Vector(u.x/s, u.y/s, u.z/s);
+}
+
+// triple scalar product (u dot (v cross w))
+inline float TripleScalarProduct(Vector u, Vector v, Vector w)
+{
+ return float( (u.x * (v.y*w.z - v.z*w.y)) +
+ (u.y * (-v.x*w.z + v.z*w.x)) +
+ (u.z * (v.x*w.y - v.y*w.x)) );
+ //return u*(v^w);
+
+}
+
+
+
+//------------------------------------------------------------------------//
+// Matrix Class and matrix functions
+//------------------------------------------------------------------------//
+
+class Matrix3x3 {
+public:
+ // elements eij: i -> row, j -> column
+ float e11, e12, e13, e21, e22, e23, e31, e32, e33;
+
+ Matrix3x3(void);
+ Matrix3x3( float r1c1, float r1c2, float r1c3,
+ float r2c1, float r2c2, float r2c3,
+ float r3c1, float r3c2, float r3c3 );
+
+ float det(void);
+ Matrix3x3 Transpose(void);
+ Matrix3x3 Inverse(void);
+
+ Matrix3x3& operator+=(Matrix3x3 m);
+ Matrix3x3& operator-=(Matrix3x3 m);
+ Matrix3x3& operator*=(float s);
+ Matrix3x3& operator/=(float s);
+};
+
+inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2);
+inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2);
+inline Matrix3x3 operator/(Matrix3x3 m, float s);
+inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2);
+inline Matrix3x3 operator*(Matrix3x3 m, float s);
+inline Matrix3x3 operator*(float s, Matrix3x3 m);
+inline Vector operator*(Matrix3x3 m, Vector u);
+inline Vector operator*(Vector u, Matrix3x3 m);
+
+
+
+
+
+inline Matrix3x3::Matrix3x3(void)
+{
+ e11 = 0;
+ e12 = 0;
+ e13 = 0;
+ e21 = 0;
+ e22 = 0;
+ e23 = 0;
+ e31 = 0;
+ e32 = 0;
+ e33 = 0;
+}
+
+inline Matrix3x3::Matrix3x3( float r1c1, float r1c2, float r1c3,
+ float r2c1, float r2c2, float r2c3,
+ float r3c1, float r3c2, float r3c3 )
+{
+ e11 = r1c1;
+ e12 = r1c2;
+ e13 = r1c3;
+ e21 = r2c1;
+ e22 = r2c2;
+ e23 = r2c3;
+ e31 = r3c1;
+ e32 = r3c2;
+ e33 = r3c3;
+}
+
+inline float Matrix3x3::det(void)
+{
+ return e11*e22*e33 -
+ e11*e32*e23 +
+ e21*e32*e13 -
+ e21*e12*e33 +
+ e31*e12*e23 -
+ e31*e22*e13;
+}
+
+inline Matrix3x3 Matrix3x3::Transpose(void)
+{
+ return Matrix3x3(e11,e21,e31,e12,e22,e32,e13,e23,e33);
+}
+
+inline Matrix3x3 Matrix3x3::Inverse(void)
+{
+ float d = e11*e22*e33 -
+ e11*e32*e23 +
+ e21*e32*e13 -
+ e21*e12*e33 +
+ e31*e12*e23 -
+ e31*e22*e13;
+
+ if (d == 0) d = 1;
+
+ return Matrix3x3( (e22*e33-e23*e32)/d,
+ -(e12*e33-e13*e32)/d,
+ (e12*e23-e13*e22)/d,
+ -(e21*e33-e23*e31)/d,
+ (e11*e33-e13*e31)/d,
+ -(e11*e23-e13*e21)/d,
+ (e21*e32-e22*e31)/d,
+ -(e11*e32-e12*e31)/d,
+ (e11*e22-e12*e21)/d );
+}
+
+inline Matrix3x3& Matrix3x3::operator+=(Matrix3x3 m)
+{
+ e11 += m.e11;
+ e12 += m.e12;
+ e13 += m.e13;
+ e21 += m.e21;
+ e22 += m.e22;
+ e23 += m.e23;
+ e31 += m.e31;
+ e32 += m.e32;
+ e33 += m.e33;
+ return *this;
+}
+
+inline Matrix3x3& Matrix3x3::operator-=(Matrix3x3 m)
+{
+ e11 -= m.e11;
+ e12 -= m.e12;
+ e13 -= m.e13;
+ e21 -= m.e21;
+ e22 -= m.e22;
+ e23 -= m.e23;
+ e31 -= m.e31;
+ e32 -= m.e32;
+ e33 -= m.e33;
+ return *this;
+}
+
+inline Matrix3x3& Matrix3x3::operator*=(float s)
+{
+ e11 *= s;
+ e12 *= s;
+ e13 *= s;
+ e21 *= s;
+ e22 *= s;
+ e23 *= s;
+ e31 *= s;
+ e32 *= s;
+ e33 *= s;
+ return *this;
+}
+
+inline Matrix3x3& Matrix3x3::operator/=(float s)
+{
+ e11 /= s;
+ e12 /= s;
+ e13 /= s;
+ e21 /= s;
+ e22 /= s;
+ e23 /= s;
+ e31 /= s;
+ e32 /= s;
+ e33 /= s;
+ return *this;
+}
+
+inline Matrix3x3 operator+(Matrix3x3 m1, Matrix3x3 m2)
+{
+ return Matrix3x3( m1.e11+m2.e11,
+ m1.e12+m2.e12,
+ m1.e13+m2.e13,
+ m1.e21+m2.e21,
+ m1.e22+m2.e22,
+ m1.e23+m2.e23,
+ m1.e31+m2.e31,
+ m1.e32+m2.e32,
+ m1.e33+m2.e33);
+}
+
+inline Matrix3x3 operator-(Matrix3x3 m1, Matrix3x3 m2)
+{
+ return Matrix3x3( m1.e11-m2.e11,
+ m1.e12-m2.e12,
+ m1.e13-m2.e13,
+ m1.e21-m2.e21,
+ m1.e22-m2.e22,
+ m1.e23-m2.e23,
+ m1.e31-m2.e31,
+ m1.e32-m2.e32,
+ m1.e33-m2.e33);
+}
+
+inline Matrix3x3 operator/(Matrix3x3 m, float s)
+{
+ return Matrix3x3( m.e11/s,
+ m.e12/s,
+ m.e13/s,
+ m.e21/s,
+ m.e22/s,
+ m.e23/s,
+ m.e31/s,
+ m.e32/s,
+ m.e33/s);
+}
+
+inline Matrix3x3 operator*(Matrix3x3 m1, Matrix3x3 m2)
+{
+ return Matrix3x3( m1.e11*m2.e11 + m1.e12*m2.e21 + m1.e13*m2.e31,
+ m1.e11*m2.e12 + m1.e12*m2.e22 + m1.e13*m2.e32,
+ m1.e11*m2.e13 + m1.e12*m2.e23 + m1.e13*m2.e33,
+ m1.e21*m2.e11 + m1.e22*m2.e21 + m1.e23*m2.e31,
+ m1.e21*m2.e12 + m1.e22*m2.e22 + m1.e23*m2.e32,
+ m1.e21*m2.e13 + m1.e22*m2.e23 + m1.e23*m2.e33,
+ m1.e31*m2.e11 + m1.e32*m2.e21 + m1.e33*m2.e31,
+ m1.e31*m2.e12 + m1.e32*m2.e22 + m1.e33*m2.e32,
+ m1.e31*m2.e13 + m1.e32*m2.e23 + m1.e33*m2.e33 );
+}
+
+inline Matrix3x3 operator*(Matrix3x3 m, float s)
+{
+ return Matrix3x3( m.e11*s,
+ m.e12*s,
+ m.e13*s,
+ m.e21*s,
+ m.e22*s,
+ m.e23*s,
+ m.e31*s,
+ m.e32*s,
+ m.e33*s);
+}
+
+inline Matrix3x3 operator*(float s, Matrix3x3 m)
+{
+ return Matrix3x3( m.e11*s,
+ m.e12*s,
+ m.e13*s,
+ m.e21*s,
+ m.e22*s,
+ m.e23*s,
+ m.e31*s,
+ m.e32*s,
+ m.e33*s);
+}
+
+inline Vector operator*(Matrix3x3 m, Vector u)
+{
+ return Vector( m.e11*u.x + m.e12*u.y + m.e13*u.z,
+ m.e21*u.x + m.e22*u.y + m.e23*u.z,
+ m.e31*u.x + m.e32*u.y + m.e33*u.z);
+}
+
+inline Vector operator*(Vector u, Matrix3x3 m)
+{
+ return Vector( u.x*m.e11 + u.y*m.e21 + u.z*m.e31,
+ u.x*m.e12 + u.y*m.e22 + u.z*m.e32,
+ u.x*m.e13 + u.y*m.e23 + u.z*m.e33);
+}
+
+//------------------------------------------------------------------------//
+// Quaternion Class and Quaternion functions
+//------------------------------------------------------------------------//
+
+class Quaternion {
+public:
+ float n; // number (scalar) part
+ Vector v; // vector part: v.x, v.y, v.z
+
+ Quaternion(void);
+ Quaternion(float e0, float e1, float e2, float e3);
+
+ float Magnitude(void);
+ Vector GetVector(void);
+ float GetScalar(void);
+ Quaternion operator+=(Quaternion q);
+ Quaternion operator-=(Quaternion q);
+ Quaternion operator*=(float s);
+ Quaternion operator/=(float s);
+ Quaternion operator~(void) const { return Quaternion(n, -v.x, -v.y, -v.z);}
+};
+
+inline Quaternion operator+(Quaternion q1, Quaternion q2);
+inline Quaternion operator-(Quaternion q1, Quaternion q2);
+inline Quaternion operator*(Quaternion q1, Quaternion q2);
+inline Quaternion operator*(Quaternion q, float s);
+inline Quaternion operator*(float s, Quaternion q);
+inline Quaternion operator*(Quaternion q, Vector v);
+inline Quaternion operator*(Vector v, Quaternion q);
+inline Quaternion operator/(Quaternion q, float s);
+inline float QGetAngle(Quaternion q);
+inline Vector QGetAxis(Quaternion q);
+inline Quaternion QRotate(Quaternion q1, Quaternion q2);
+inline Vector QVRotate(Quaternion q, Vector v);
+inline Quaternion MakeQFromEulerAngles(float x, float y, float z);
+inline Vector MakeEulerAnglesFromQ(Quaternion q);
+
+
+inline Quaternion::Quaternion(void)
+{
+ n = 0;
+ v.x = 0;
+ v.y = 0;
+ v.z = 0;
+}
+
+inline Quaternion::Quaternion(float e0, float e1, float e2, float e3)
+{
+ n = e0;
+ v.x = e1;
+ v.y = e2;
+ v.z = e3;
+}
+
+inline float Quaternion::Magnitude(void)
+{
+ return (float) sqrt(n*n + v.x*v.x + v.y*v.y + v.z*v.z);
+}
+
+inline Vector Quaternion::GetVector(void)
+{
+ return Vector(v.x, v.y, v.z);
+}
+
+inline float Quaternion::GetScalar(void)
+{
+ return n;
+}
+
+inline Quaternion Quaternion::operator+=(Quaternion q)
+{
+ n += q.n;
+ v.x += q.v.x;
+ v.y += q.v.y;
+ v.z += q.v.z;
+ return *this;
+}
+
+inline Quaternion Quaternion::operator-=(Quaternion q)
+{
+ n -= q.n;
+ v.x -= q.v.x;
+ v.y -= q.v.y;
+ v.z -= q.v.z;
+ return *this;
+}
+
+inline Quaternion Quaternion::operator*=(float s)
+{
+ n *= s;
+ v.x *= s;
+ v.y *= s;
+ v.z *= s;
+ return *this;
+}
+
+inline Quaternion Quaternion::operator/=(float s)
+{
+ n /= s;
+ v.x /= s;
+ v.y /= s;
+ v.z /= s;
+ return *this;
+}
+
+/*inline Quaternion Quaternion::operator~()
+{
+return Quaternion(n, -v.x, -v.y, -v.z);
+}*/
+
+inline Quaternion operator+(Quaternion q1, Quaternion q2)
+{
+ return Quaternion( q1.n + q2.n,
+ q1.v.x + q2.v.x,
+ q1.v.y + q2.v.y,
+ q1.v.z + q2.v.z);
+}
+
+inline Quaternion operator-(Quaternion q1, Quaternion q2)
+{
+ return Quaternion( q1.n - q2.n,
+ q1.v.x - q2.v.x,
+ q1.v.y - q2.v.y,
+ q1.v.z - q2.v.z);
+}
+
+inline Quaternion operator*(Quaternion q1, Quaternion q2)
+{
+ return Quaternion( q1.n*q2.n - q1.v.x*q2.v.x - q1.v.y*q2.v.y - q1.v.z*q2.v.z,
+ q1.n*q2.v.x + q1.v.x*q2.n + q1.v.y*q2.v.z - q1.v.z*q2.v.y,
+ q1.n*q2.v.y + q1.v.y*q2.n + q1.v.z*q2.v.x - q1.v.x*q2.v.z,
+ q1.n*q2.v.z + q1.v.z*q2.n + q1.v.x*q2.v.y - q1.v.y*q2.v.x);
+}
+
+inline Quaternion operator*(Quaternion q, float s)
+{
+ return Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s);
+}
+
+inline Quaternion operator*(float s, Quaternion q)
+{
+ return Quaternion(q.n*s, q.v.x*s, q.v.y*s, q.v.z*s);
+}
+
+inline Quaternion operator*(Quaternion q, Vector v)
+{
+ return Quaternion( -(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z),
+ q.n*v.x + q.v.y*v.z - q.v.z*v.y,
+ q.n*v.y + q.v.z*v.x - q.v.x*v.z,
+ q.n*v.z + q.v.x*v.y - q.v.y*v.x);
+}
+
+inline Quaternion operator*(Vector v, Quaternion q)
+{
+ return Quaternion( -(q.v.x*v.x + q.v.y*v.y + q.v.z*v.z),
+ q.n*v.x + q.v.z*v.y - q.v.y*v.z,
+ q.n*v.y + q.v.x*v.z - q.v.z*v.x,
+ q.n*v.z + q.v.y*v.x - q.v.x*v.y);
+}
+
+inline Quaternion operator/(Quaternion q, float s)
+{
+ return Quaternion(q.n/s, q.v.x/s, q.v.y/s, q.v.z/s);
+}
+
+inline float QGetAngle(Quaternion q)
+{
+ return (float) (2*acosf(q.n));
+}
+
+inline Vector QGetAxis(Quaternion q)
+{
+ Vector v;
+ float m;
+
+ v = q.GetVector();
+ m = v.Magnitude();
+
+ if (m <= tol)
+ return Vector();
+ else
+ return v/m;
+}
+
+inline Quaternion QRotate(Quaternion q1, Quaternion q2)
+{
+ return q1*q2*(~q1);
+}
+
+inline Vector QVRotate(Quaternion q, Vector v)
+{
+ Quaternion t;
+
+
+ t = q*v*(~q);
+
+ return t.GetVector();
+}
+
+inline Quaternion MakeQFromEulerAngles(float x, float y, float z)
+{
+ Quaternion q;
+ double roll = DegreesToRadians(x);
+ double pitch = DegreesToRadians(y);
+ double yaw = DegreesToRadians(z);
+
+ double cyaw, cpitch, croll, syaw, spitch, sroll;
+ double cyawcpitch, syawspitch, cyawspitch, syawcpitch;
+
+ cyaw = cos(0.5f * yaw);
+ cpitch = cos(0.5f * pitch);
+ croll = cos(0.5f * roll);
+ syaw = sin(0.5f * yaw);
+ spitch = sin(0.5f * pitch);
+ sroll = sin(0.5f * roll);
+
+ cyawcpitch = cyaw*cpitch;
+ syawspitch = syaw*spitch;
+ cyawspitch = cyaw*spitch;
+ syawcpitch = syaw*cpitch;
+
+ q.n = (float) (cyawcpitch * croll + syawspitch * sroll);
+ q.v.x = (float) (cyawcpitch * sroll - syawspitch * croll);
+ q.v.y = (float) (cyawspitch * croll + syawcpitch * sroll);
+ q.v.z = (float) (syawcpitch * croll - cyawspitch * sroll);
+
+ return q;
+}
+
+inline Vector MakeEulerAnglesFromQ(Quaternion q)
+{
+ double r11, r21, r31, r32, r33, r12, r13;
+ double q00, q11, q22, q33;
+ double tmp;
+ Vector u;
+
+ q00 = q.n * q.n;
+ q11 = q.v.x * q.v.x;
+ q22 = q.v.y * q.v.y;
+ q33 = q.v.z * q.v.z;
+
+ r11 = q00 + q11 - q22 - q33;
+ r21 = 2 * (q.v.x*q.v.y + q.n*q.v.z);
+ r31 = 2 * (q.v.x*q.v.z - q.n*q.v.y);
+ r32 = 2 * (q.v.y*q.v.z + q.n*q.v.x);
+ r33 = q00 - q11 - q22 + q33;
+
+ tmp = fabs(r31);
+ if(tmp > 0.999999)
+ {
+ r12 = 2 * (q.v.x*q.v.y - q.n*q.v.z);
+ r13 = 2 * (q.v.x*q.v.z + q.n*q.v.y);
+
+ u.x = RadiansToDegrees(0.0f); //roll
+ u.y = RadiansToDegrees((float) (-(pi/2) * r31/tmp)); // pitch
+ u.z = RadiansToDegrees((float) atan2(-r12, -r31*r13)); // yaw
+ return u;
+ }
+
+ u.x = RadiansToDegrees((float) atan2(r32, r33)); // roll
+ u.y = RadiansToDegrees((float) asinf(-r31)); // pitch
+ u.z = RadiansToDegrees((float) atan2(r21, r11)); // yaw
+ return u;
+
+
+}
+
+
+
+
+
+#endif
\ No newline at end of file
--- /dev/null
+// Pointer.h: interface for the Pointer class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef _POINTER_H
+#define _POINTER_H
+
+template <class T>
+class Pointer
+{
+private:
+ void Destroy()
+ {
+ p = NULL;
+ GC::Collect();
+ }
+
+public:
+ T* p;
+
+ Pointer( T* p_ = NULL ) : p( p_ )
+ {
+ }
+
+ ~Pointer()
+ {
+ GC::SetTotalBytesAllocated( GC::GetTotalBytesAllocated() - sizeof( *p ) );
+
+ p->~T(); // Explicitely call the destructor
+
+ Destroy();
+
+ }
+
+ Pointer& operator = ( Pointer<T>& p_ )
+ {
+ return operator = ( ( T* ) p_);
+ }
+
+ Pointer& operator = ( T* p_ )
+ {
+ Destroy();
+ p = p_;
+ return *this;
+ }
+
+ operator T*()
+ {
+ return p;
+ }
+
+ T& operator*()
+ {
+ return *p;
+ }
+
+ T* operator->()
+ {
+ return p;
+ }
+
+// For automatic type conversion during new call
+ operator void**()
+ {
+ return ( void** ) & p;
+ }
+};
+
+
+#endif
--- /dev/null
+#include "Quaternions.h"
+
+// Functions
+quaternion Quat_Mult(quaternion q1, quaternion q2)
+{
+ quaternion QResult;
+ float a, b, c, d, e, f, g, h;
+ a = (q1.w + q1.x) * (q2.w + q2.x);
+ b = (q1.z - q1.y) * (q2.y - q2.z);
+ c = (q1.w - q1.x) * (q2.y + q2.z);
+ d = (q1.y + q1.z) * (q2.w - q2.x);
+ e = (q1.x + q1.z) * (q2.x + q2.y);
+ f = (q1.x - q1.z) * (q2.x - q2.y);
+ g = (q1.w + q1.y) * (q2.w - q2.z);
+ h = (q1.w - q1.y) * (q2.w + q2.z);
+ QResult.w = b + (-e - f + g + h) / 2;
+ QResult.x = a - (e + f + g + h) / 2;
+ QResult.y = c + (e - f + g - h) / 2;
+ QResult.z = d + (e - f - g + h) / 2;
+ return QResult;
+}
+
+
+
+quaternion To_Quat(Matrix_t m)
+{
+ // From Jason Shankel, (C) 2000.
+ static quaternion Quat;
+
+ static double Tr = m[0][0] + m[1][1] + m[2][2] + 1.0, fourD;
+ static double q[4];
+
+ static int i,j,k;
+ if (Tr >= 1.0)
+ {
+ fourD = 2.0*fast_sqrt(Tr);
+ q[3] = fourD/4.0;
+ q[0] = (m[2][1] - m[1][2]) / fourD;
+ q[1] = (m[0][2] - m[2][0]) / fourD;
+ q[2] = (m[1][0] - m[0][1]) / fourD;
+ }
+ else
+ {
+ if (m[0][0] > m[1][1])
+ {
+ i = 0;
+ }
+ else
+ {
+ i = 1;
+ }
+ if (m[2][2] > m[i][i])
+ {
+ i = 2;
+ }
+ j = (i+1)%3;
+ k = (j+1)%3;
+ fourD = 2.0*fast_sqrt(m[i][i] - m[j][j] - m[k][k] + 1.0);
+ q[i] = fourD / 4.0;
+ q[j] = (m[j][i] + m[i][j]) / fourD;
+ q[k] = (m[k][i] + m[i][k]) / fourD;
+ q[3] = (m[j][k] - m[k][j]) / fourD;
+ }
+
+ Quat.x = q[0];
+ Quat.y = q[1];
+ Quat.z = q[2];
+ Quat.w = q[3];
+ return Quat;
+}
+void Quat_2_Matrix(quaternion Quat, Matrix_t m)
+{
+ // From the GLVelocity site (http://glvelocity.gamedev.net)
+ float fW = Quat.w;
+ float fX = Quat.x;
+ float fY = Quat.y;
+ float fZ = Quat.z;
+ float fXX = fX * fX;
+ float fYY = fY * fY;
+ float fZZ = fZ * fZ;
+ m[0][0] = 1.0f - 2.0f * (fYY + fZZ);
+ m[1][0] = 2.0f * (fX * fY + fW * fZ);
+ m[2][0] = 2.0f * (fX * fZ - fW * fY);
+ m[3][0] = 0.0f;
+ m[0][1] = 2.0f * (fX * fY - fW * fZ);
+ m[1][1] = 1.0f - 2.0f * (fXX + fZZ);
+ m[2][1] = 2.0f * (fY * fZ + fW * fX);
+ m[3][1] = 0.0f;
+ m[0][2] = 2.0f * (fX * fZ + fW * fY);
+ m[1][2] = 2.0f * (fX * fZ - fW * fX);
+ m[2][2] = 1.0f - 2.0f * (fXX + fYY);
+ m[3][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+}
+quaternion To_Quat(angle_axis Ang_Ax)
+{
+ // From the Quaternion Powers article on gamedev.net
+ static quaternion Quat;
+
+ Quat.x = Ang_Ax.x * sin(Ang_Ax.angle / 2);
+ Quat.y = Ang_Ax.y * sin(Ang_Ax.angle / 2);
+ Quat.z = Ang_Ax.z * sin(Ang_Ax.angle / 2);
+ Quat.w = cos(Ang_Ax.angle / 2);
+ return Quat;
+}
+angle_axis Quat_2_AA(quaternion Quat)
+{
+ static angle_axis Ang_Ax;
+ static float scale, tw;
+ tw = (float)acosf(Quat.w) * 2;
+ scale = (float)sin(tw / 2.0);
+ Ang_Ax.x = Quat.x / scale;
+ Ang_Ax.y = Quat.y / scale;
+ Ang_Ax.z = Quat.z / scale;
+
+ Ang_Ax.angle = 2.0 * acosf(Quat.w)/(float)PI*180;
+ return Ang_Ax;
+}
+
+quaternion To_Quat(int In_Degrees, euler Euler)
+{
+ // From the gamasutra quaternion article
+ static quaternion Quat;
+ static float cr, cp, cy, sr, sp, sy, cpcy, spsy;
+ //If we are in Degree mode, convert to Radians
+ if (In_Degrees) {
+ Euler.x = Euler.x * (float)PI / 180;
+ Euler.y = Euler.y * (float)PI / 180;
+ Euler.z = Euler.z * (float)PI / 180;
+ }
+ //Calculate trig identities
+ //Formerly roll, pitch, yaw
+ cr = float(cos(Euler.x/2));
+ cp = float(cos(Euler.y/2));
+ cy = float(cos(Euler.z/2));
+ sr = float(sin(Euler.x/2));
+ sp = float(sin(Euler.y/2));
+ sy = float(sin(Euler.z/2));
+
+ cpcy = cp * cy;
+ spsy = sp * sy;
+ Quat.w = cr * cpcy + sr * spsy;
+ Quat.x = sr * cpcy - cr * spsy;
+ Quat.y = cr * sp * cy + sr * cp * sy;
+ Quat.z = cr * cp * sy - sr * sp * cy;
+
+ return Quat;
+}
+
+quaternion QNormalize(quaternion Quat)
+{
+ static float norm;
+ norm = Quat.x * Quat.x +
+ Quat.y * Quat.y +
+ Quat.z * Quat.z +
+ Quat.w * Quat.w;
+ Quat.x = float(Quat.x / norm);
+ Quat.y = float(Quat.y / norm);
+ Quat.z = float(Quat.z / norm);
+ Quat.w = float(Quat.w / norm);
+ return Quat;
+}
+
+XYZ Quat2Vector(quaternion Quat)
+{
+ QNormalize(Quat);
+
+ float fW = Quat.w;
+ float fX = Quat.x;
+ float fY = Quat.y;
+ float fZ = Quat.z;
+
+ XYZ tempvec;
+
+ tempvec.x = 2.0f*(fX*fZ-fW*fY);
+ tempvec.y = 2.0f*(fY*fZ+fW*fX);
+ tempvec.z = 1.0f-2.0f*(fX*fX+fY*fY);
+
+ return tempvec;
+}
+
+bool PointInTriangle(Vector *p, Vector normal, float p11, float p12, float p13, float p21, float p22, float p23, float p31, float p32, float p33)
+{
+ static float u0, u1, u2;
+ static float v0, v1, v2;
+ static float a, b;
+ static float max;
+ static int i, j;
+ static bool bInter;
+ static float pointv[3];
+ static float p1v[3];
+ static float p2v[3];
+ static float p3v[3];
+ static float normalv[3];
+
+ bInter=0;
+
+ pointv[0]=p->x;
+ pointv[1]=p->y;
+ pointv[2]=p->z;
+
+
+ p1v[0]=p11;
+ p1v[1]=p12;
+ p1v[2]=p13;
+
+ p2v[0]=p21;
+ p2v[1]=p22;
+ p2v[2]=p23;
+
+ p3v[0]=p31;
+ p3v[1]=p32;
+ p3v[2]=p33;
+
+ normalv[0]=normal.x;
+ normalv[1]=normal.y;
+ normalv[2]=normal.z;
+
+#define ABS(X) (((X)<0.f)?-(X):(X) )
+#define MAX(A, B) (((A)<(B))?(B):(A))
+ max = MAX(MAX(ABS(normalv[0]), ABS(normalv[1])), ABS(normalv[2]));
+#undef MAX
+ if (max == ABS(normalv[0])) {i = 1; j = 2;} // y, z
+ if (max == ABS(normalv[1])) {i = 0; j = 2;} // x, z
+ if (max == ABS(normalv[2])) {i = 0; j = 1;} // x, y
+#undef ABS
+
+ u0 = pointv[i] - p1v[i];
+ v0 = pointv[j] - p1v[j];
+ u1 = p2v[i] - p1v[i];
+ v1 = p2v[j] - p1v[j];
+ u2 = p3v[i] - p1v[i];
+ v2 = p3v[j] - p1v[j];
+
+ if (u1 > -1.0e-05f && u1 < 1.0e-05f)// == 0.0f)
+ {
+ b = u0 / u2;
+ if (0.0f <= b && b <= 1.0f)
+ {
+ a = (v0 - b * v2) / v1;
+ if ((a >= 0.0f) && (( a + b ) <= 1.0f))
+ bInter = 1;
+ }
+ }
+ else
+ {
+ b = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
+ if (0.0f <= b && b <= 1.0f)
+ {
+ a = (u0 - b * u2) / u1;
+ if ((a >= 0.0f) && (( a + b ) <= 1.0f ))
+ bInter = 1;
+ }
+ }
+
+ return bInter;
+}
+
+bool LineFacet(Vector p1,Vector p2,Vector pa,Vector pb,Vector pc,Vector *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static Vector n,pa1,pa2,pa3;
+
+ //Calculate the parameters for the plane
+ n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+ n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+ n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+ n.Normalize();
+ d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+ //Calculate the position on the line that intersects the plane
+ denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+ p->x = p1.x + mu * (p2.x - p1.x);
+ p->y = p1.y + mu * (p2.y - p1.y);
+ p->z = p1.z + mu * (p2.z - p1.z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, n, pa.x, pa.y, pa.z, pb.x, pb.y, pb.z, pc.x, pc.y, pc.z)){return 0;}
+
+ return 1;
+}
+
+bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3)
+{
+ static float u0, u1, u2;
+ static float v0, v1, v2;
+ static float a, b;
+ static float max;
+ static int i, j;
+ static bool bInter = 0;
+ static float pointv[3];
+ static float p1v[3];
+ static float p2v[3];
+ static float p3v[3];
+ static float normalv[3];
+
+ bInter=0;
+
+ pointv[0]=p->x;
+ pointv[1]=p->y;
+ pointv[2]=p->z;
+
+
+ p1v[0]=p1->x;
+ p1v[1]=p1->y;
+ p1v[2]=p1->z;
+
+ p2v[0]=p2->x;
+ p2v[1]=p2->y;
+ p2v[2]=p2->z;
+
+ p3v[0]=p3->x;
+ p3v[1]=p3->y;
+ p3v[2]=p3->z;
+
+ normalv[0]=normal.x;
+ normalv[1]=normal.y;
+ normalv[2]=normal.z;
+
+#define ABS(X) (((X)<0.f)?-(X):(X) )
+#define MAX(A, B) (((A)<(B))?(B):(A))
+ max = MAX(MAX(ABS(normalv[0]), ABS(normalv[1])), ABS(normalv[2]));
+#undef MAX
+ if (max == ABS(normalv[0])) {i = 1; j = 2;} // y, z
+ if (max == ABS(normalv[1])) {i = 0; j = 2;} // x, z
+ if (max == ABS(normalv[2])) {i = 0; j = 1;} // x, y
+#undef ABS
+
+ u0 = pointv[i] - p1v[i];
+ v0 = pointv[j] - p1v[j];
+ u1 = p2v[i] - p1v[i];
+ v1 = p2v[j] - p1v[j];
+ u2 = p3v[i] - p1v[i];
+ v2 = p3v[j] - p1v[j];
+
+ if (u1 > -1.0e-05f && u1 < 1.0e-05f)// == 0.0f)
+ {
+ b = u0 / u2;
+ if (0.0f <= b && b <= 1.0f)
+ {
+ a = (v0 - b * v2) / v1;
+ if ((a >= 0.0f) && (( a + b ) <= 1.0f))
+ bInter = 1;
+ }
+ }
+ else
+ {
+ b = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
+ if (0.0f <= b && b <= 1.0f)
+ {
+ a = (u0 - b * u2) / u1;
+ if ((a >= 0.0f) && (( a + b ) <= 1.0f ))
+ bInter = 1;
+ }
+ }
+
+ return bInter;
+}
+
+bool LineFacet(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static XYZ n,pa1,pa2,pa3;
+
+ //Calculate the parameters for the plane
+ n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+ n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+ n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+ Normalise(&n);
+ d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+ //Calculate the position on the line that intersects the plane
+ denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+ p->x = p1.x + mu * (p2.x - p1.x);
+ p->y = p1.y + mu * (p2.y - p1.y);
+ p->z = p1.z + mu * (p2.z - p1.z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+
+ return 1;
+}
+
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static XYZ n,pa1,pa2,pa3;
+
+ //Calculate the parameters for the plane
+ n.x = (pb.y - pa.y)*(pc.z - pa.z) - (pb.z - pa.z)*(pc.y - pa.y);
+ n.y = (pb.z - pa.z)*(pc.x - pa.x) - (pb.x - pa.x)*(pc.z - pa.z);
+ n.z = (pb.x - pa.x)*(pc.y - pa.y) - (pb.y - pa.y)*(pc.x - pa.x);
+ Normalise(&n);
+ d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+ //Calculate the position on the line that intersects the plane
+ denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+ p->x = p1.x + mu * (p2.x - p1.x);
+ p->y = p1.y + mu * (p2.y - p1.y);
+ p->z = p1.z + mu * (p2.z - p1.z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+
+ return 1;
+}
+
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc, XYZ n, XYZ *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static XYZ pa1,pa2,pa3;
+
+ //Calculate the parameters for the plane
+ d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+
+ //Calculate the position on the line that intersects the plane
+ denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+ p->x = p1.x + mu * (p2.x - p1.x);
+ p->y = p1.y + mu * (p2.y - p1.y);
+ p->z = p1.z + mu * (p2.z - p1.z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
+ return 1;
+}
+
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc, XYZ *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static XYZ pa1,pa2,pa3,n;
+
+ //Calculate the parameters for the plane
+ n.x = (pb->y - pa->y)*(pc->z - pa->z) - (pb->z - pa->z)*(pc->y - pa->y);
+ n.y = (pb->z - pa->z)*(pc->x - pa->x) - (pb->x - pa->x)*(pc->z - pa->z);
+ n.z = (pb->x - pa->x)*(pc->y - pa->y) - (pb->y - pa->y)*(pc->x - pa->x);
+ Normalise(&n);
+ d = - n.x * pa->x - n.y * pa->y - n.z * pa->z;
+
+
+ //Calculate the position on the line that intersects the plane
+ denom = n.x * (p2->x - p1->x) + n.y * (p2->y - p1->y) + n.z * (p2->z - p1->z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n.x * p1->x + n.y * p1->y + n.z * p1->z) / denom;
+ p->x = p1->x + mu * (p2->x - p1->x);
+ p->y = p1->y + mu * (p2->y - p1->y);
+ p->z = p1->z + mu * (p2->z - p1->z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, n, pa, pb, pc)){return 0;}
+ return 1;
+}
+
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc, XYZ *n, XYZ *p)
+{
+ static float d;
+ static float a1,a2,a3;
+ static float total,denom,mu;
+ static XYZ pa1,pa2,pa3;
+
+ //Calculate the parameters for the plane
+ d = - n->x * pa->x - n->y * pa->y - n->z * pa->z;
+
+ //Calculate the position on the line that intersects the plane
+ denom = n->x * (p2->x - p1->x) + n->y * (p2->y - p1->y) + n->z * (p2->z - p1->z);
+ if (abs(denom) < 0.0000001) // Line and plane don't intersect
+ return 0;
+ mu = - (d + n->x * p1->x + n->y * p1->y + n->z * p1->z) / denom;
+ p->x = p1->x + mu * (p2->x - p1->x);
+ p->y = p1->y + mu * (p2->y - p1->y);
+ p->z = p1->z + mu * (p2->z - p1->z);
+ if (mu < 0 || mu > 1) // Intersection not along line segment
+ return 0;
+
+ if(!PointInTriangle( p, *n, pa, pb, pc)){return 0;}
+ return 1;
+}
+
--- /dev/null
+
+#ifndef _QUATERNIONS_H_
+#define _QUATERNIONS_H_
+
+#ifndef WIN32
+#pragma mark -
+#endif
+
+//#include "Carbon.h"
+#include "math.h"
+#include "Physicsmath.h"
+#include "gl.h"
+
+/**> Quaternion Structures <**/
+#define PI 3.14159265355555897932384626
+#define RADIANS 0
+#define DEGREES 1
+#define deg2rad .0174532925
+
+//using namespace std;
+typedef float Matrix_t [4][4];
+struct euler
+{
+ float x, y, z;
+};
+struct angle_axis
+{
+ float x, y, z, angle;
+};
+struct quaternion
+{
+ float x, y, z, w;
+};
+
+class XYZ{
+public:
+ float x;
+ float y;
+ float z;
+ inline XYZ operator+(XYZ add);
+ inline XYZ operator-(XYZ add);
+ inline XYZ operator*(float add);
+ inline XYZ operator*(XYZ add);
+ inline XYZ operator/(float add);
+ inline void operator+=(XYZ add);
+ inline void operator-=(XYZ add);
+ inline void operator*=(float add);
+ inline void operator*=(XYZ add);
+ inline void operator/=(float add);
+ inline void operator=(float add);
+ inline void vec(Vector add);
+ inline bool operator==(XYZ add);
+};
+
+/*********************> Quaternion Function definition <********/
+quaternion To_Quat(int Degree_Flag, euler Euler);
+quaternion To_Quat(angle_axis Ang_Ax);
+quaternion To_Quat(Matrix_t m);
+angle_axis Quat_2_AA(quaternion Quat);
+void Quat_2_Matrix(quaternion Quat, Matrix_t m);
+quaternion Normalize(quaternion Quat);
+quaternion Quat_Mult(quaternion q1, quaternion q2);
+quaternion QNormalize(quaternion Quat);
+XYZ Quat2Vector(quaternion Quat);
+
+inline void CrossProduct(XYZ *P, XYZ *Q, XYZ *V);
+inline void CrossProduct(XYZ P, XYZ Q, XYZ *V);
+inline void Normalise(XYZ *vectory);
+inline float normaldotproduct(XYZ point1, XYZ point2);
+inline float fast_sqrt (register float arg);
+bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3);
+bool LineFacet(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p);
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ *p);
+float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc,XYZ n, XYZ *p);
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc,XYZ *n, XYZ *p);
+float LineFacetd(XYZ *p1,XYZ *p2,XYZ *pa,XYZ *pb,XYZ *pc, XYZ *p);
+bool PointInTriangle(Vector *p, Vector normal, float p11, float p12, float p13, float p21, float p22, float p23, float p31, float p32, float p33);
+bool LineFacet(Vector p1,Vector p2,Vector pa,Vector pb,Vector pc,Vector *p);
+inline void ReflectVector(XYZ *vel, XYZ *n);
+inline XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang);
+inline XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang);
+inline float findDistance(XYZ *point1, XYZ *point2);
+inline float findLength(XYZ *point1);
+inline float findLengthfast(XYZ *point1);
+inline float findDistancefast(XYZ *point1, XYZ *point2);
+inline float findDistancefast(XYZ point1, XYZ point2);
+inline float findDistancefastflat(XYZ *point1, XYZ *point2);
+inline float dotproduct(XYZ *point1, XYZ *point2);
+bool sphere_line_intersection (
+ float x1, float y1 , float z1,
+ float x2, float y2 , float z2,
+ float x3, float y3 , float z3, float r );
+bool sphere_line_intersection (
+ XYZ *p1, XYZ *p2, XYZ *p3, float *r );
+inline bool DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd, float *Distance, XYZ *Intersection );
+
+
+inline void Normalise(XYZ *vectory) {
+ static float d;
+ d = fast_sqrt(vectory->x*vectory->x+vectory->y*vectory->y+vectory->z*vectory->z);
+ if(d==0){return;}
+ vectory->x /= d;
+ vectory->y /= d;
+ vectory->z /= d;
+}
+
+inline XYZ XYZ::operator+(XYZ add){
+ static XYZ ne;
+ ne=add;
+ ne.x+=x;
+ ne.y+=y;
+ ne.z+=z;
+ return ne;
+}
+
+inline XYZ XYZ::operator-(XYZ add){
+ static XYZ ne;
+ ne=add;
+ ne.x=x-ne.x;
+ ne.y=y-ne.y;
+ ne.z=z-ne.z;
+ return ne;
+}
+
+inline XYZ XYZ::operator*(float add){
+ static XYZ ne;
+ ne.x=x*add;
+ ne.y=y*add;
+ ne.z=z*add;
+ return ne;
+}
+
+inline XYZ XYZ::operator*(XYZ add){
+ static XYZ ne;
+ ne.x=x*add.x;
+ ne.y=y*add.y;
+ ne.z=z*add.z;
+ return ne;
+}
+
+inline XYZ XYZ::operator/(float add){
+ static XYZ ne;
+ ne.x=x/add;
+ ne.y=y/add;
+ ne.z=z/add;
+ return ne;
+}
+
+inline void XYZ::operator+=(XYZ add){
+ x+=add.x;
+ y+=add.y;
+ z+=add.z;
+}
+
+inline void XYZ::operator-=(XYZ add){
+ x=x-add.x;
+ y=y-add.y;
+ z=z-add.z;
+}
+
+inline void XYZ::operator*=(float add){
+ x=x*add;
+ y=y*add;
+ z=z*add;
+}
+
+inline void XYZ::operator*=(XYZ add){
+ x=x*add.x;
+ y=y*add.y;
+ z=z*add.z;
+}
+
+inline void XYZ::operator/=(float add){
+ x=x/add;
+ y=y/add;
+ z=z/add;
+}
+
+inline void XYZ::operator=(float add){
+ x=add;
+ y=add;
+ z=add;
+}
+
+inline void XYZ::vec(Vector add){
+ x=add.x;
+ y=add.y;
+ z=add.z;
+}
+
+inline bool XYZ::operator==(XYZ add){
+ if(x==add.x&&y==add.y&&z==add.z)return 1;
+ return 0;
+}
+
+inline void CrossProduct(XYZ *P, XYZ *Q, XYZ *V){
+ V->x = P->y * Q->z - P->z * Q->y;
+ V->y = P->z * Q->x - P->x * Q->z;
+ V->z = P->x * Q->y - P->y * Q->x;
+}
+
+inline void CrossProduct(XYZ P, XYZ Q, XYZ *V){
+ V->x = P.y * Q.z - P.z * Q.y;
+ V->y = P.z * Q.x - P.x * Q.z;
+ V->z = P.x * Q.y - P.y * Q.x;
+}
+
+inline float fast_sqrt (register float arg)
+{
+#ifdef WIN32
+ return sqrtf( arg);
+#else
+ // Can replace with slower return std::sqrt(arg);
+ register float result;
+
+ if (arg == 0.0) return 0.0;
+
+ asm {
+ frsqrte result,arg // Calculate Square root
+ }
+
+ // Newton Rhapson iterations.
+ result = result + 0.5 * result * (1.0 - arg * result * result);
+ result = result + 0.5 * result * (1.0 - arg * result * result);
+
+ return result * arg;
+#endif
+}
+
+inline float normaldotproduct(XYZ point1, XYZ point2){
+ static GLfloat returnvalue;
+ Normalise(&point1);
+ Normalise(&point2);
+ returnvalue=(point1.x*point2.x+point1.y*point2.y+point1.z*point2.z);
+ return returnvalue;
+}
+
+inline void ReflectVector(XYZ *vel, XYZ *n)
+{
+ static XYZ vn;
+ static XYZ vt;
+ static float dotprod;
+
+ dotprod=dotproduct(n,vel);
+ vn.x=n->x*dotprod;
+ vn.y=n->y*dotprod;
+ vn.z=n->z*dotprod;
+
+ vt.x=vel->x-vn.x;
+ vt.y=vel->y-vn.y;
+ vt.z=vel->z-vn.z;
+
+ vel->x = vt.x - vn.x;
+ vel->y = vt.y - vn.y;
+ vel->z = vt.z - vn.z;
+}
+
+inline float dotproduct(XYZ *point1, XYZ *point2){
+ static GLfloat returnvalue;
+ returnvalue=(point1->x*point2->x+point1->y*point2->y+point1->z*point2->z);
+ return returnvalue;
+}
+
+inline float findDistance(XYZ *point1, XYZ *point2){
+ return(fast_sqrt((point1->x-point2->x)*(point1->x-point2->x)+(point1->y-point2->y)*(point1->y-point2->y)+(point1->z-point2->z)*(point1->z-point2->z)));
+}
+
+inline float findLength(XYZ *point1){
+ return(fast_sqrt((point1->x)*(point1->x)+(point1->y)*(point1->y)+(point1->z)*(point1->z)));
+}
+
+
+inline float findLengthfast(XYZ *point1){
+ return((point1->x)*(point1->x)+(point1->y)*(point1->y)+(point1->z)*(point1->z));
+}
+
+inline float findDistancefast(XYZ *point1, XYZ *point2){
+ return((point1->x-point2->x)*(point1->x-point2->x)+(point1->y-point2->y)*(point1->y-point2->y)+(point1->z-point2->z)*(point1->z-point2->z));
+}
+
+inline float findDistancefast(XYZ point1, XYZ point2){
+ return((point1.x-point2.x)*(point1.x-point2.x)+(point1.y-point2.y)*(point1.y-point2.y)+(point1.z-point2.z)*(point1.z-point2.z));
+}
+
+inline float findDistancefastflat(XYZ *point1, XYZ *point2){
+ return((point1->x-point2->x)*(point1->x-point2->x)+(point1->z-point2->z)*(point1->z-point2->z));
+}
+
+inline XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang){
+ static XYZ newpoint;
+ if(xang){
+ xang*=6.283185f;
+ xang/=360;
+ }
+ if(yang){
+ yang*=6.283185f;
+ yang/=360;
+ }
+ if(zang){
+ zang*=6.283185f;
+ zang/=360;
+ }
+
+
+ if(yang){
+ newpoint.z=thePoint.z*cosf(yang)-thePoint.x*sinf(yang);
+ newpoint.x=thePoint.z*sinf(yang)+thePoint.x*cosf(yang);
+ thePoint.z=newpoint.z;
+ thePoint.x=newpoint.x;
+ }
+
+ if(zang){
+ newpoint.x=thePoint.x*cosf(zang)-thePoint.y*sinf(zang);
+ newpoint.y=thePoint.y*cosf(zang)+thePoint.x*sinf(zang);
+ thePoint.x=newpoint.x;
+ thePoint.y=newpoint.y;
+ }
+
+ if(xang){
+ newpoint.y=thePoint.y*cosf(xang)-thePoint.z*sinf(xang);
+ newpoint.z=thePoint.y*sinf(xang)+thePoint.z*cosf(xang);
+ thePoint.z=newpoint.z;
+ thePoint.y=newpoint.y;
+ }
+
+ return thePoint;
+}
+
+inline float square( float f ) { return (f*f) ;}
+
+inline bool sphere_line_intersection (
+ float x1, float y1 , float z1,
+ float x2, float y2 , float z2,
+ float x3, float y3 , float z3, float r )
+{
+
+ // x1,y1,z1 P1 coordinates (point of line)
+ // x2,y2,z2 P2 coordinates (point of line)
+ // x3,y3,z3, r P3 coordinates and radius (sphere)
+ // x,y,z intersection coordinates
+ //
+ // This function returns a pointer array which first index indicates
+ // the number of intersection point, followed by coordinate pairs.
+
+ static float x , y , z;
+ static float a, b, c, mu, i ;
+
+ if(x1>x3+r&&x2>x3+r)return(0);
+ if(x1<x3-r&&x2<x3-r)return(0);
+ if(y1>y3+r&&y2>y3+r)return(0);
+ if(y1<y3-r&&y2<y3-r)return(0);
+ if(z1>z3+r&&z2>z3+r)return(0);
+ if(z1<z3-r&&z2<z3-r)return(0);
+ a = square(x2 - x1) + square(y2 - y1) + square(z2 - z1);
+ b = 2* ( (x2 - x1)*(x1 - x3)
+ + (y2 - y1)*(y1 - y3)
+ + (z2 - z1)*(z1 - z3) ) ;
+ c = square(x3) + square(y3) +
+ square(z3) + square(x1) +
+ square(y1) + square(z1) -
+ 2* ( x3*x1 + y3*y1 + z3*z1 ) - square(r) ;
+ i = b * b - 4 * a * c ;
+
+ if ( i < 0.0 )
+ {
+ // no intersection
+ return(0);
+ }
+ return(1);
+}
+
+inline bool sphere_line_intersection (
+ XYZ *p1, XYZ *p2, XYZ *p3, float *r )
+{
+
+ // x1,p1->y,p1->z P1 coordinates (point of line)
+ // p2->x,p2->y,p2->z P2 coordinates (point of line)
+ // p3->x,p3->y,p3->z, r P3 coordinates and radius (sphere)
+ // x,y,z intersection coordinates
+ //
+ // This function returns a pointer array which first index indicates
+ // the number of intersection point, followed by coordinate pairs.
+
+ static float x , y , z;
+ static float a, b, c, mu, i ;
+
+ if(p1->x>p3->x+*r&&p2->x>p3->x+*r)return(0);
+ if(p1->x<p3->x-*r&&p2->x<p3->x-*r)return(0);
+ if(p1->y>p3->y+*r&&p2->y>p3->y+*r)return(0);
+ if(p1->y<p3->y-*r&&p2->y<p3->y-*r)return(0);
+ if(p1->z>p3->z+*r&&p2->z>p3->z+*r)return(0);
+ if(p1->z<p3->z-*r&&p2->z<p3->z-*r)return(0);
+ a = square(p2->x - p1->x) + square(p2->y - p1->y) + square(p2->z - p1->z);
+ b = 2* ( (p2->x - p1->x)*(p1->x - p3->x)
+ + (p2->y - p1->y)*(p1->y - p3->y)
+ + (p2->z - p1->z)*(p1->z - p3->z) ) ;
+ c = square(p3->x) + square(p3->y) +
+ square(p3->z) + square(p1->x) +
+ square(p1->y) + square(p1->z) -
+ 2* ( p3->x*p1->x + p3->y*p1->y + p3->z*p1->z ) - square(*r) ;
+ i = b * b - 4 * a * c ;
+
+ if ( i < 0.0 )
+ {
+ // no intersection
+ return(0);
+ }
+ return(1);
+}
+
+inline XYZ DoRotationRadian(XYZ thePoint, float xang, float yang, float zang){
+ static XYZ newpoint;
+ static XYZ oldpoint;
+
+ oldpoint=thePoint;
+
+ if(yang!=0){
+ newpoint.z=oldpoint.z*cosf(yang)-oldpoint.x*sinf(yang);
+ newpoint.x=oldpoint.z*sinf(yang)+oldpoint.x*cosf(yang);
+ oldpoint.z=newpoint.z;
+ oldpoint.x=newpoint.x;
+ }
+
+ if(zang!=0){
+ newpoint.x=oldpoint.x*cosf(zang)-oldpoint.y*sinf(zang);
+ newpoint.y=oldpoint.y*cosf(zang)+oldpoint.x*sinf(zang);
+ oldpoint.x=newpoint.x;
+ oldpoint.y=newpoint.y;
+ }
+
+ if(xang!=0){
+ newpoint.y=oldpoint.y*cosf(xang)-oldpoint.z*sinf(xang);
+ newpoint.z=oldpoint.y*sinf(xang)+oldpoint.z*cosf(xang);
+ oldpoint.z=newpoint.z;
+ oldpoint.y=newpoint.y;
+ }
+
+ return oldpoint;
+
+}
+
+inline bool DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd, float *Distance, XYZ *Intersection )
+{
+ float LineMag;
+ float U;
+
+ LineMag = findDistance( LineEnd, LineStart );
+
+ U = ( ( ( Point->x - LineStart->x ) * ( LineEnd->x - LineStart->x ) ) +
+ ( ( Point->y - LineStart->y ) * ( LineEnd->y - LineStart->y ) ) +
+ ( ( Point->z - LineStart->z ) * ( LineEnd->z - LineStart->z ) ) ) /
+ ( LineMag * LineMag );
+
+ if( U < 0.0f || U > 1.0f )
+ return 0; // closest point does not fall within the line segment
+
+ Intersection->x = LineStart->x + U * ( LineEnd->x - LineStart->x );
+ Intersection->y = LineStart->y + U * ( LineEnd->y - LineStart->y );
+ Intersection->z = LineStart->z + U * ( LineEnd->z - LineStart->z );
+
+ *Distance = findDistance( Point, Intersection );
+
+ return 1;
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+
+#include "Random.h"
+#include "stdlib.h"
+
+
+int randSeed = 1;
+
+short Random()
+{
+ /*unsigned int value = (unsigned int)randSeed;
+ unsigned int out=0;
+ int i=31;
+
+ while (i > 0)
+ {
+ value ^= 0x81010000;
+ value ^= out;
+ if (value & 1)
+ {
+ value >>= 1;
+ value |= 0x80000000;
+ }
+ else
+ value >>= 1;
+ out <<= 1;
+ out |= (value&0x1);
+ i--;
+ }
+ if (value&0x80000000)
+ {
+ out <<= 1;
+ out |= 1;
+ }
+ else
+ out <<= 1;
+
+ randSeed += out;
+ */
+ return rand();
+}
--- /dev/null
+#ifndef _RANDOM_H_
+#define _RANDOM_H_
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+extern int randSeed;
+short Random ();
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "Skeleton.h"
+
+extern float multiplier;
+extern float gravity;
+extern Skeleton testskeleton;
+extern Terrain terrain;
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern Objects objects;
+extern Sprites sprites;
+extern int environment;
+extern float terraindetail;
+extern float camerashake;
+extern bool freeze;
+extern int detail;
+extern XYZ envsound[30];
+extern float envsoundvol[30];
+extern int numenvsounds;
+extern float envsoundlife[30];
+extern int bonus;
+extern float bonustime;
+extern int tutoriallevel;
+
+extern int whichjointstartarray[26];
+extern int whichjointendarray[26];
+
+#include "Game.h"
+extern Game * pgame;
+extern bool visibleloading;
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+void dealloc2(void* param){
+ free(param);
+ param=0;
+}
+
+void Muscle::DoConstraint(bool spinny)
+{
+ static XYZ vel;
+ static XYZ midp;
+ static XYZ newpoint1,newpoint2;
+
+ static float oldlength;
+ static float relaxlength;
+
+ oldlength=length;
+
+ if(type!=boneconnect)relaxlength=findDistance(&parent1->position,&parent2->position);
+
+ if(type==boneconnect)strength=1;
+ if(type==constraint)strength=0;
+
+ if(strength<0)strength=0;
+ if(strength>1)strength=1;
+
+ length-=(length-relaxlength)*(1-strength)*multiplier*10000;
+ length-=(length-targetlength)*(strength)*multiplier*10000;
+ if(strength==0)length=relaxlength;
+
+ if((relaxlength-length>0&&relaxlength-oldlength<0)||(relaxlength-length<0&&relaxlength-oldlength>0))length=relaxlength;
+
+ //if(!broken){
+ if(length<minlength)length=minlength;
+ if(length>maxlength)length=maxlength;
+ //}
+ /*
+ if(broken){
+ if(length<minlength*.6)length=minlength*.6;
+ if(length>maxlength*1.4)length=maxlength*1.4;
+ }
+ */
+ if(length==relaxlength)return;
+
+ //Find midpoint
+ midp=(parent1->position*parent1->mass+parent2->position*parent2->mass)/(parent1->mass+parent2->mass);
+ //Find vector from midpoint to second vector
+ vel=parent2->position-midp;
+ //Change to unit vector
+ Normalise(&vel);
+ //Apply velocity change
+ newpoint1=midp-vel*length*(parent2->mass/(parent1->mass+parent2->mass));
+ newpoint2=midp+vel*length*(parent1->mass/(parent1->mass+parent2->mass));
+ if(!freeze&&spinny){
+ parent1->velocity=parent1->velocity+(newpoint1-parent1->position)/multiplier/4;
+ parent2->velocity=parent2->velocity+(newpoint2-parent2->position)/multiplier/4;
+ }
+ else
+ {
+ parent1->velocity=parent1->velocity+(newpoint1-parent1->position);
+ parent2->velocity=parent2->velocity+(newpoint2-parent2->position);
+ }
+ //Move child point to within certain distance of parent point
+ parent1->position=newpoint1;
+ parent2->position=newpoint2;
+}
+
+void Skeleton::FindForwardsfirst()
+{
+ //Find forward vectors
+ CrossProduct(joints[forwardjoints[1]].position-joints[forwardjoints[0]].position,joints[forwardjoints[2]].position-joints[forwardjoints[0]].position,&forward);
+ Normalise(&forward);
+
+ CrossProduct(joints[lowforwardjoints[1]].position-joints[lowforwardjoints[0]].position,joints[lowforwardjoints[2]].position-joints[lowforwardjoints[0]].position,&lowforward);
+ Normalise(&lowforward);
+
+ //Special forwards
+ specialforward[0]=forward;
+ specialforward[1]=forward;
+ specialforward[2]=forward;
+ specialforward[3]=forward;
+ specialforward[4]=forward;
+
+}
+void Skeleton::FindForwards()
+{
+ //Find forward vectors
+ CrossProduct(joints[forwardjoints[1]].position-joints[forwardjoints[0]].position,joints[forwardjoints[2]].position-joints[forwardjoints[0]].position,&forward);
+ Normalise(&forward);
+
+ CrossProduct(joints[lowforwardjoints[1]].position-joints[lowforwardjoints[0]].position,joints[lowforwardjoints[2]].position-joints[lowforwardjoints[0]].position,&lowforward);
+ Normalise(&lowforward);
+
+ //Special forwards
+ specialforward[0]=forward;
+
+ specialforward[1]=joints[jointlabels[rightshoulder]].position+joints[jointlabels[rightwrist]].position;
+ specialforward[1]=joints[jointlabels[rightelbow]].position-specialforward[1]/2;
+ specialforward[1]+=forward*.4;
+ Normalise(&specialforward[1]);
+ specialforward[2]=joints[jointlabels[leftshoulder]].position+joints[jointlabels[leftwrist]].position;
+ specialforward[2]=joints[jointlabels[leftelbow]].position-specialforward[2]/2;
+ specialforward[2]+=forward*.4;
+ Normalise(&specialforward[2]);
+
+ specialforward[3]=joints[jointlabels[righthip]].position+joints[jointlabels[rightankle]].position;
+ specialforward[3]=specialforward[3]/2-joints[jointlabels[rightknee]].position;
+ specialforward[3]+=lowforward*.4;
+ Normalise(&specialforward[3]);
+ specialforward[4]=joints[jointlabels[lefthip]].position+joints[jointlabels[leftankle]].position;
+ specialforward[4]=specialforward[4]/2-joints[jointlabels[leftknee]].position;
+ specialforward[4]+=lowforward*.4;
+ Normalise(&specialforward[4]);
+}
+
+float Skeleton::DoConstraints(XYZ *coords,float *scale)
+{
+ static float friction=1.5;
+ static float elasticity=.3;
+ static XYZ bounceness;
+ static XYZ oldpos[100];
+ static int numrepeats=3;
+ static float groundlevel=.15;
+ static float soundvolume;
+ static int i,j,k,l,m;
+ static XYZ temp,start,end;
+ static XYZ terrainnormal;
+ static float r=.05;
+ static float r2=.08;
+ static int whichhit;
+ //static int whichjointstart,whichjointend;
+ static float distance;
+ static float frictionness;
+ static XYZ terrainlight;
+ static int whichpatchx;
+ static int whichpatchz;
+ static float damage;
+ static bool freely;
+ static float tempmult;
+ static bool breaking;
+ breaking=0;
+
+ damage=0;
+
+ if(free){
+ freetime+=multiplier;
+
+ whichpatchx=coords->x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=coords->z/(terrain.size/subdivision*terrain.scale*terraindetail);
+
+ terrainlight=*coords;
+ objects.SphereCheckPossible(&terrainlight, 1);
+ /*
+ for(i=0; i<num_joints; i++){
+ oldpos[i]=joints[i].position;
+ }*/
+
+ //Add velocity
+ for(i=0; i<num_joints; i++){
+ //if(!isnormal(joints[i].velocity.x)||!isnormal(joints[i].velocity.y)||!isnormal(joints[i].velocity.z))joints[i].velocity=0;
+ joints[i].position=joints[i].position+joints[i].velocity*multiplier;
+ groundlevel=.15;
+ if(joints[i].label==head)groundlevel=.8;
+ if(joints[i].label==righthand||joints[i].label==rightwrist||joints[i].label==rightelbow)groundlevel=.2;
+ if(joints[i].label==lefthand||joints[i].label==leftwrist||joints[i].label==leftelbow)groundlevel=.2;
+ joints[i].position.y-=groundlevel;
+ //if(!joints[i].locked&&!broken)joints[i].velocity+=joints[i].velchange*multiplier*10*(500-longdead)/500;
+ joints[i].oldvelocity=joints[i].velocity;
+ }
+ tempmult=multiplier;
+ //multiplier/=numrepeats;
+ for(j=0; j<numrepeats; j++){
+ if(!joints[jointlabels[rightknee]].locked&&!joints[jointlabels[righthip]].locked){
+ temp=joints[jointlabels[rightknee]].position-(joints[jointlabels[righthip]].position+joints[jointlabels[rightankle]].position)/2;
+ while(normaldotproduct(temp,lowforward)>-.1&&!sphere_line_intersection(&joints[jointlabels[righthip]].position,&joints[jointlabels[rightankle]].position,&joints[jointlabels[rightknee]].position,&r)){
+ joints[jointlabels[rightknee]].position-=lowforward*.05;
+ if(spinny)joints[jointlabels[rightknee]].velocity-=lowforward*.05/multiplier/4;
+ else joints[jointlabels[rightknee]].velocity-=lowforward*.05;
+ joints[jointlabels[rightankle]].position+=lowforward*.025;
+ if(spinny)joints[jointlabels[rightankle]].velocity+=lowforward*.025/multiplier/4;
+ else joints[jointlabels[rightankle]].velocity+=lowforward*.25;
+ joints[jointlabels[righthip]].position+=lowforward*.025;
+ if(spinny)joints[jointlabels[righthip]].velocity+=lowforward*.025/multiplier/4;
+ else joints[jointlabels[righthip]].velocity+=lowforward*.025;
+ temp=joints[jointlabels[rightknee]].position-(joints[jointlabels[righthip]].position+joints[jointlabels[rightankle]].position)/2;
+ }
+ }
+ if(!joints[jointlabels[leftknee]].locked&&!joints[jointlabels[righthip]].locked){
+ temp=joints[jointlabels[leftknee]].position-(joints[jointlabels[lefthip]].position+joints[jointlabels[leftankle]].position)/2;
+ while(normaldotproduct(temp,lowforward)>-.1&&!sphere_line_intersection(&joints[jointlabels[lefthip]].position,&joints[jointlabels[leftankle]].position,&joints[jointlabels[leftknee]].position,&r)){
+ joints[jointlabels[leftknee]].position-=lowforward*.05;
+ if(spinny)joints[jointlabels[leftknee]].velocity-=lowforward*.05/multiplier/4;
+ else joints[jointlabels[leftknee]].velocity-=lowforward*.05;
+ joints[jointlabels[leftankle]].position+=lowforward*.025;
+ if(spinny)joints[jointlabels[leftankle]].velocity+=lowforward*.025/multiplier/4;
+ else joints[jointlabels[leftankle]].velocity+=lowforward*.25;
+ joints[jointlabels[lefthip]].position+=lowforward*.025;
+ if(spinny)joints[jointlabels[lefthip]].velocity+=lowforward*.025/multiplier/4;
+ else joints[jointlabels[lefthip]].velocity+=lowforward*.025;
+ temp=joints[jointlabels[leftknee]].position-(joints[jointlabels[lefthip]].position+joints[jointlabels[leftankle]].position)/2;
+ }
+ }
+ /*
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz])
+ for(m=0;m<terrain.patchobjectnum[whichpatchx][whichpatchz];m++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][m];
+ if(k<objects.numobjects&&k>=0)
+ if(objects.possible[k]){
+ temp=joints[jointlabels[head]].position*(*scale)+*coords;
+ if(objects.model[k].SphereCheck(&temp, 0.06, &start, &objects.position[k], &objects.rotation[k])!=-1){
+ //temp=(joints[jointlabels[head]].position*(*scale)+*coords)-start;
+ //Normalise(&temp);
+ //joints[jointlabels[head]].position=((temp*.2+start)-*coords)/(*scale);
+ joints[jointlabels[head]].position=(temp-*coords)/(*scale);
+ }
+ }
+ } */
+
+
+ //Ears check
+ /*XYZ startheadpos;
+ startheadpos=joints[jointlabels[head]].position;
+ XYZ headpos;
+ headpos=joints[jointlabels[head]].position+(joints[jointlabels[head]].position-joints[jointlabels[neck]].position);
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz])
+ for(m=0;m<terrain.patchobjectnum[whichpatchx][whichpatchz];m++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][m];
+ if(k<objects.numobjects&&k>=0)
+ if(objects.possible[k]){
+ friction=objects.friction[k];
+ start=joints[jointlabels[head]].position*(*scale)+*coords;
+ end=(headpos)*(*scale)+*coords;
+ whichhit=objects.model[k].LineCheckPossible(&start,&end,&temp,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ if(joints[jointlabels[head]].label==groin&&!joints[jointlabels[head]].locked&&joints[jointlabels[head]].delay<=0){
+ joints[jointlabels[head]].locked=1;
+ joints[jointlabels[head]].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=headpos.x*(*scale)+coords->x;
+ gLoc[1]=headpos.y*(*scale)+coords->y;
+ gLoc[2]=headpos.z*(*scale)+coords->z;
+ vel[0]=joints[jointlabels[head]].velocity.x;
+ vel[1]=joints[jointlabels[head]].velocity.y;
+ vel[2]=joints[jointlabels[head]].velocity.z;
+ PlaySoundEx( landsound1, samp[landsound1], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound1], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound1], 128);
+ FSOUND_SetPaused(channels[landsound1], FALSE);
+
+ breaking=1;
+ }
+
+ if(joints[jointlabels[head]].label==head&&!joints[jointlabels[head]].locked&&joints[jointlabels[head]].delay<=0){
+ joints[jointlabels[head]].locked=1;
+ joints[jointlabels[head]].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=headpos.x*(*scale)+coords->x;
+ gLoc[1]=headpos.y*(*scale)+coords->y;
+ gLoc[2]=headpos.z*(*scale)+coords->z;
+ vel[0]=joints[jointlabels[head]].velocity.x;
+ vel[1]=joints[jointlabels[head]].velocity.y;
+ vel[2]=joints[jointlabels[head]].velocity.z;
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ if(terrainnormal.y>.8)freefall=0;
+ bounceness=terrainnormal*findLength(&joints[jointlabels[head]].velocity)*(abs(normaldotproduct(joints[jointlabels[head]].velocity,terrainnormal)));
+ if(findLengthfast(&joints[jointlabels[head]].velocity)>findLengthfast(&joints[jointlabels[head]].oldvelocity)){
+ bounceness=0;
+ joints[jointlabels[head]].velocity=joints[jointlabels[head]].oldvelocity;
+ }
+ if(findLengthfast(&bounceness)>4000&&breaking){
+ objects.model[k].MakeDecal(breakdecal,DoRotation(temp-objects.position[k],0,-objects.rotation[k],0),.4,.5,Random()%360);
+ sprites.MakeSprite(cloudsprite, headpos*(*scale)+*coords,joints[jointlabels[head]].velocity*.06, 1,1,1, 4, .2);
+ breaking=0;
+ camerashake+=.6;
+
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=headpos.x*(*scale)+coords->x;
+ gLoc[1]=headpos.y*(*scale)+coords->y;
+ gLoc[2]=headpos.z*(*scale)+coords->z;
+ vel[0]=joints[jointlabels[head]].velocity.x;
+ vel[1]=joints[jointlabels[head]].velocity.y;
+ vel[2]=joints[jointlabels[head]].velocity.z;
+ PlaySoundEx( breaksound2, samp[breaksound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound2], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound2], 300);
+ FSOUND_SetPaused(channels[breaksound2], FALSE);
+
+ envsound[numenvsounds]=*coords;
+ envsoundvol[numenvsounds]=64;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ if(objects.type[k]==treetrunktype){
+ objects.rotx[k]+=joints[jointlabels[head]].velocity.x*multiplier*.4;
+ objects.roty[k]+=joints[jointlabels[head]].velocity.z*multiplier*.4;
+ objects.rotx[k+1]+=joints[jointlabels[head]].velocity.x*multiplier*.4;
+ objects.roty[k+1]+=joints[jointlabels[head]].velocity.z*multiplier*.4;
+ }
+ if(!joints[jointlabels[head]].locked)damage+=findLengthfast(&bounceness)/2500;
+ ReflectVector(&joints[jointlabels[head]].velocity,&terrainnormal);
+ frictionness=abs(normaldotproduct(joints[jointlabels[head]].velocity,terrainnormal));//findLength(&bounceness)/findLength(&joints[jointlabels[head]].velocity);
+ joints[jointlabels[head]].velocity-=bounceness;
+ if(1-friction*frictionness>0)joints[jointlabels[head]].velocity*=1-friction*frictionness;
+ else joints[jointlabels[head]].velocity=0;
+ if(findLengthfast(&bounceness)>2500){
+ Normalise(&bounceness);
+ bounceness=bounceness*50;
+ }
+ joints[jointlabels[head]].velocity+=bounceness*elasticity;
+
+
+ if(!joints[jointlabels[head]].locked)
+ if(findLengthfast(&joints[jointlabels[head]].velocity)<1){
+ joints[jointlabels[head]].locked=1;
+ //joints[jointlabels[head]].velocity*=3;
+ }
+ if(findLengthfast(&bounceness)>500)sprites.MakeSprite(cloudsprite, headpos*(*scale)+*coords,joints[jointlabels[head]].velocity*.06, 1,1,1, .5, .2);
+ joints[jointlabels[head]].position=(temp-*coords)/(*scale)+(startheadpos-headpos)+terrainnormal*.005;
+ if(longdead>100)broken=1;
+ }
+ }
+ }
+ */
+
+ for(i=0; i<num_joints; i++){
+ //joints[i].delay-=multiplier/1.5;
+ if(joints[i].locked)
+ if(!spinny)if(findLengthfast(&joints[i].velocity)>320)joints[i].locked=0;
+ if(spinny)if(findLengthfast(&joints[i].velocity)>600)joints[i].locked=0;
+ if(joints[i].delay>0){
+ freely=1;
+ for(j=0;j<num_joints;j++){
+ if(joints[j].locked)freely=0;
+ }
+ if(freely)joints[i].delay-=multiplier*3;
+ }
+ //if(joints[i].delay>0)
+ //if(findLengthfast(&joints[i].velocity)>700&&joints[i].label!=head)joints[i].delay-=multiplier;
+ }
+
+ if(num_muscles)
+ for(i=0; i<num_muscles; i++){
+ //Length constraints
+ //muscles[i].DoConstraint(broken);
+ muscles[i].DoConstraint(spinny);
+ }
+
+ for(i=0; i<num_joints; i++){
+ //joints[i].delay-=multiplier/1.5;
+ //Length constraints
+ //Ground constraint
+ groundlevel=0;
+ if(joints[i].position.y*(*scale)+coords->y<terrain.getHeight(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z)+groundlevel){
+ freefall=0;
+ friction=1.5;
+ if(joints[i].label==groin&&!joints[i].locked&&joints[i].delay<=0){
+ joints[i].locked=1;
+ joints[i].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ if(tutoriallevel!=1||id==0){
+ PlaySoundEx( landsound1, samp[landsound1], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound1], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound1], 128);
+ FSOUND_SetPaused(channels[landsound1], FALSE);
+ }
+ breaking=1;
+ }
+
+ if(joints[i].label==head&&!joints[i].locked&&joints[i].delay<=0){
+ joints[i].locked=1;
+ joints[i].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ if(tutoriallevel!=1||id==0){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ }
+
+ terrainnormal=terrain.getNormal(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z);
+ ReflectVector(&joints[i].velocity,&terrainnormal);
+ bounceness=terrainnormal*findLength(&joints[i].velocity)*(abs(normaldotproduct(joints[i].velocity,terrainnormal)));
+ if(!joints[i].locked)damage+=findLengthfast(&bounceness)/4000;
+ if(findLengthfast(&joints[i].velocity)<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(joints[i].velocity,terrainnormal));//findLength(&bounceness)/findLength(&joints[i].velocity);
+ joints[i].velocity-=bounceness;
+ if(1-friction*frictionness>0)joints[i].velocity*=1-friction*frictionness;
+ else joints[i].velocity=0;
+
+ if(tutoriallevel!=1||id==0)
+ if(findLengthfast(&bounceness)>8000&&breaking){
+ objects.model[k].MakeDecal(breakdecal,DoRotation(temp-objects.position[k],0,-objects.rotation[k],0),.4,.5,Random()%360);
+ sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, 1,1,1, 4, .2);
+ //sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, 1,1,1, 1, .2);
+ breaking=0;
+ camerashake+=.6;
+
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ PlaySoundEx( breaksound2, samp[breaksound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound2], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound2], 300);
+ FSOUND_SetPaused(channels[breaksound2], FALSE);
+
+ envsound[numenvsounds]=*coords;
+ envsoundvol[numenvsounds]=64;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ if(findLengthfast(&bounceness)>2500){
+ Normalise(&bounceness);
+ bounceness=bounceness*50;
+ }
+
+ joints[i].velocity+=bounceness*elasticity;
+
+ if(findLengthfast(&joints[i].velocity)>findLengthfast(&joints[i].oldvelocity)){
+ bounceness=0;
+ joints[i].velocity=joints[i].oldvelocity;
+ }
+
+
+ if(joints[i].locked==0)
+ if(findLengthfast(&joints[i].velocity)<1)joints[i].locked=1;
+
+ if(environment==snowyenvironment&&findLengthfast(&bounceness)>500&&terrain.getOpacity(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z)<.2){
+ terrainlight=terrain.getLighting(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z);
+ sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, terrainlight.x,terrainlight.y,terrainlight.z, .5, .7);
+ if(detail==2)terrain.MakeDecal(bodyprintdecal, joints[i].position*(*scale)+*coords,.4,.4,0);
+ }
+ else if(environment==desertenvironment&&findLengthfast(&bounceness)>500&&terrain.getOpacity(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z)<.2){
+ terrainlight=terrain.getLighting(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z);
+ sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, terrainlight.x*190/255,terrainlight.y*170/255,terrainlight.z*108/255, .5, .7);
+ }
+
+ else if(environment==grassyenvironment&&findLengthfast(&bounceness)>500&&terrain.getOpacity(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z)<.2){
+ terrainlight=terrain.getLighting(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z);
+ sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, terrainlight.x*90/255,terrainlight.y*70/255,terrainlight.z*8/255, .5, .5);
+ }
+ else if(findLengthfast(&bounceness)>500)sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, terrainlight.x,terrainlight.y,terrainlight.z, .5, .2);
+
+
+ joints[i].position.y=(terrain.getHeight(joints[i].position.x*(*scale)+coords->x,joints[i].position.z*(*scale)+coords->z)+groundlevel-coords->y)/(*scale);
+ if(longdead>100)broken=1;
+ }
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz])
+ for(m=0;m<terrain.patchobjectnum[whichpatchx][whichpatchz];m++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][m];
+ if(k<objects.numobjects&&k>=0)
+ if(objects.possible[k]){
+ friction=objects.friction[k];
+ start=joints[i].realoldposition;
+ end=joints[i].position*(*scale)+*coords;
+ whichhit=objects.model[k].LineCheckPossible(&start,&end,&temp,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ if(joints[i].label==groin&&!joints[i].locked&&joints[i].delay<=0){
+ joints[i].locked=1;
+ joints[i].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ if(tutoriallevel!=1||id==0){
+ PlaySoundEx( landsound1, samp[landsound1], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound1], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound1], 128);
+ FSOUND_SetPaused(channels[landsound1], FALSE);
+ }
+ breaking=1;
+ }
+
+ if(joints[i].label==head&&!joints[i].locked&&joints[i].delay<=0){
+ joints[i].locked=1;
+ joints[i].delay=1;
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ if(tutoriallevel!=1||id==0){
+ PlaySoundEx( landsound2, samp[landsound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[landsound2], gLoc, vel);
+ FSOUND_SetVolume(channels[landsound2], 128);
+ FSOUND_SetPaused(channels[landsound2], FALSE);
+ }
+ }
+
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ if(terrainnormal.y>.8)freefall=0;
+ bounceness=terrainnormal*findLength(&joints[i].velocity)*(abs(normaldotproduct(joints[i].velocity,terrainnormal)));
+ if(findLengthfast(&joints[i].velocity)>findLengthfast(&joints[i].oldvelocity)){
+ bounceness=0;
+ joints[i].velocity=joints[i].oldvelocity;
+ }
+ if(tutoriallevel!=1||id==0)
+ if(findLengthfast(&bounceness)>4000&&breaking){
+ objects.model[k].MakeDecal(breakdecal,DoRotation(temp-objects.position[k],0,-objects.rotation[k],0),.4,.5,Random()%360);
+ sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, 1,1,1, 4, .2);
+ breaking=0;
+ camerashake+=.6;
+
+ static float gLoc[3];
+ static float vel[3];
+ gLoc[0]=joints[i].position.x*(*scale)+coords->x;
+ gLoc[1]=joints[i].position.y*(*scale)+coords->y;
+ gLoc[2]=joints[i].position.z*(*scale)+coords->z;
+ vel[0]=joints[i].velocity.x;
+ vel[1]=joints[i].velocity.y;
+ vel[2]=joints[i].velocity.z;
+ PlaySoundEx( breaksound2, samp[breaksound2], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[breaksound2], gLoc, vel);
+ FSOUND_SetVolume(channels[breaksound2], 300);
+ FSOUND_SetPaused(channels[breaksound2], FALSE);
+
+ envsound[numenvsounds]=*coords;
+ envsoundvol[numenvsounds]=64;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+ if(objects.type[k]==treetrunktype){
+ //if(objects.rotx[k]==0||objects.roty[k]==0){
+ /*int howmany;
+ XYZ tempvel;
+ XYZ pos;
+ if(environment==grassyenvironment)howmany=findLength(&joints[i].velocity)*4/10;
+ if(environment==snowyenvironment)howmany=findLength(&joints[i].velocity)*1/10;
+ if(environment!=desertenvironment)
+ for(j=0;j<howmany;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ pos=objects.position[k];
+ pos.y+=objects.scale[k]*15;
+ pos.x+=float(abs(Random()%100)-50)/100*objects.scale[k]*5;
+ pos.y+=float(abs(Random()%100)-50)/100*objects.scale[k]*15;
+ pos.z+=float(abs(Random()%100)-50)/100*objects.scale[k]*5;
+ sprites.MakeSprite(splintersprite, pos,tempvel*.5, 165/255+float(abs(Random()%100)-50)/400,0,0, .2+float(abs(Random()%100)-50)/1300, 1);
+ sprites.special[sprites.numsprites-1]=1;
+ }*/
+ objects.rotx[k]+=joints[i].velocity.x*multiplier*.4;
+ objects.roty[k]+=joints[i].velocity.z*multiplier*.4;
+ objects.rotx[k+1]+=joints[i].velocity.x*multiplier*.4;
+ objects.roty[k+1]+=joints[i].velocity.z*multiplier*.4;
+ }
+ if(!joints[i].locked)damage+=findLengthfast(&bounceness)/2500;
+ ReflectVector(&joints[i].velocity,&terrainnormal);
+ frictionness=abs(normaldotproduct(joints[i].velocity,terrainnormal));//findLength(&bounceness)/findLength(&joints[i].velocity);
+ joints[i].velocity-=bounceness;
+ if(1-friction*frictionness>0)joints[i].velocity*=1-friction*frictionness;
+ else joints[i].velocity=0;
+ if(findLengthfast(&bounceness)>2500){
+ Normalise(&bounceness);
+ bounceness=bounceness*50;
+ }
+ joints[i].velocity+=bounceness*elasticity;
+
+
+ if(!joints[i].locked)
+ if(findLengthfast(&joints[i].velocity)<1){
+ joints[i].locked=1;
+ //joints[i].velocity*=3;
+ }
+ if(findLengthfast(&bounceness)>500)sprites.MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, 1,1,1, .5, .2);
+ joints[i].position=(temp-*coords)/(*scale)+terrainnormal*.005;
+ if(longdead>100)broken=1;
+ }
+ }
+ }
+ joints[i].realoldposition=joints[i].position*(*scale)+*coords;
+ }
+ }
+ multiplier=tempmult;
+
+
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz])
+ for(m=0;m<terrain.patchobjectnum[whichpatchx][whichpatchz];m++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][m];
+ if(objects.possible[k]){
+ for(i=0;i<26;i++){
+ //Make this less stupid
+ start=joints[jointlabels[whichjointstartarray[i]]].position*(*scale)+*coords;
+ end=joints[jointlabels[whichjointendarray[i]]].position*(*scale)+*coords;
+ whichhit=objects.model[k].LineCheckSlidePossible(&start,&end,&temp,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ joints[jointlabels[whichjointendarray[i]]].position=(end-*coords)/(*scale);
+ for(j=0; j<num_muscles; j++){
+ if((muscles[j].parent1->label==whichjointstartarray[i]&&muscles[j].parent2->label==whichjointendarray[i])||(muscles[j].parent2->label==whichjointstartarray[i]&&muscles[j].parent1->label==whichjointendarray[i]))
+ muscles[j].DoConstraint(spinny);
+ }
+ }
+ }
+ }
+ }
+
+ for(i=0; i<num_joints; i++){
+ groundlevel=.15;
+ if(joints[i].label==head)groundlevel=.8;
+ if(joints[i].label==righthand||joints[i].label==rightwrist||joints[i].label==rightelbow)groundlevel=.2;
+ if(joints[i].label==lefthand||joints[i].label==leftwrist||joints[i].label==leftelbow)groundlevel=.2;
+ joints[i].position.y+=groundlevel;
+ joints[i].mass=1;
+ if(joints[i].label==lefthip||joints[i].label==leftknee||joints[i].label==leftankle||joints[i].label==righthip||joints[i].label==rightknee||joints[i].label==rightankle)joints[i].mass=2;
+ if(joints[i].locked){
+ joints[i].mass=4;
+ }
+ }
+
+ return damage;
+ }
+ if(!free){
+ for(i=0; i<num_muscles; i++){
+ if(muscles[i].type==boneconnect)
+ muscles[i].DoConstraint(0);
+ }
+ }
+ return 0;
+}
+
+void Skeleton::DoGravity(float *scale)
+{
+ static int i;
+ for(i=0; i<num_joints; i++){
+ if(((joints[i].label!=leftknee&&joints[i].label!=rightknee)||lowforward.y>-.1||joints[i].mass<5)&&((joints[i].label!=rightelbow&&joints[i].label!=rightelbow)||forward.y<.3))joints[i].velocity.y+=gravity*multiplier/(*scale);
+ }
+}
+
+void Skeleton::Draw(int muscleview)
+{
+ static float jointcolor[4];
+
+ if(muscleview!=2){
+ jointcolor[0]=0;
+ jointcolor[1]=0;
+ jointcolor[2]=.5;
+ jointcolor[3]=1;
+ }
+
+ if(muscleview==2){
+ jointcolor[0]=0;
+ jointcolor[1]=0;
+ jointcolor[2]=0;
+ jointcolor[3]=.5;
+ }
+ //Calc motionblur-ness
+ for(int i=0; i<num_joints; i++){
+ joints[i].oldposition=joints[i].position;
+ joints[i].blurred=findDistance(&joints[i].position,&joints[i].oldposition)*100;
+ if(joints[i].blurred<1)joints[i].blurred=1;
+ }
+
+ //Do Motionblur
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glBegin(GL_QUADS);
+ for(int i=0; i<num_joints; i++){
+ if(joints[i].hasparent){
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+ glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+ glVertex3f(joints[i].parent->position.x,joints[i].parent->position.y,joints[i].parent->position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+ glVertex3f(joints[i].parent->oldposition.x,joints[i].parent->oldposition.y,joints[i].parent->oldposition.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+ glVertex3f(joints[i].oldposition.x,joints[i].oldposition.y,joints[i].oldposition.z);
+ }
+ }
+ for(int i=0; i<num_muscles; i++){
+ if(muscles[i].type==boneconnect){
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+ glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+ glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+ glVertex3f(muscles[i].parent2->oldposition.x,muscles[i].parent2->oldposition.y,muscles[i].parent2->oldposition.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent1->blurred);
+ glVertex3f(muscles[i].parent1->oldposition.x,muscles[i].parent1->oldposition.y,muscles[i].parent1->oldposition.z);
+ }
+ }
+ glEnd();
+
+ glBegin(GL_LINES);
+ for(int i=0; i<num_joints; i++){
+ if(joints[i].hasparent){
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].blurred);
+ glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/joints[i].parent->blurred);
+ glVertex3f(joints[i].parent->position.x,joints[i].parent->position.y,joints[i].parent->position.z);
+ }
+ }
+ /*for(int i=0; i<num_joints; i++){
+ if(joints[i].hasparent){
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],1);
+ glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],1);
+ glVertex3f(joints[i].position.x+forward.x,joints[i].position.y+forward.y,joints[i].position.z+forward.z);
+ }
+ }*/
+ for(int i=0; i<num_muscles; i++){
+ if(muscles[i].type==boneconnect){
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent1->blurred);
+ glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+ glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],jointcolor[3]/muscles[i].parent2->blurred);
+ glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+ }
+ }
+ glColor3f(.6,.6,0);
+ if(muscleview==1)
+ for(int i=0; i<num_muscles; i++){
+ if(muscles[i].type!=boneconnect){
+ glVertex3f(muscles[i].parent1->position.x,muscles[i].parent1->position.y,muscles[i].parent1->position.z);
+ glVertex3f(muscles[i].parent2->position.x,muscles[i].parent2->position.y,muscles[i].parent2->position.z);
+ }
+ }
+ glEnd();
+
+ if(muscleview!=2){
+ glPointSize(3);
+ glBegin(GL_POINTS);
+ for(int i=0; i<num_joints; i++){
+ if(i!=selected)glColor4f(0,0,.5,1);
+ if(i==selected)glColor4f(1,1,0,1);
+ if(joints[i].locked&&i!=selected)glColor4f(1,0,0,1);
+ glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
+ }
+ glEnd();
+ }
+
+ //Set old position to current position
+ if(muscleview==2)
+ for(int i=0; i<num_joints; i++){
+ joints[i].oldposition=joints[i].position;
+ }
+ glDepthMask(1);
+}
+
+void Skeleton::AddJoint(float x, float y, float z, int which)
+{
+ if(num_joints<max_joints-1){
+ joints[num_joints].velocity=0;
+ joints[num_joints].position.x=x;
+ joints[num_joints].position.y=y;
+ joints[num_joints].position.z=z;
+ joints[num_joints].mass=1;
+ joints[num_joints].locked=0;
+
+ /*if(which>=num_joints||which<0)*/joints[num_joints].hasparent=0;
+ /*if(which<num_joints&&which>=0){
+ joints[num_joints].parent=&joints[which];
+ joints[num_joints].hasparent=1;
+ joints[num_joints].length=findDistance(joints[num_joints].position,joints[num_joints].parent->position);
+ }*/
+ num_joints++;
+ if(which<num_joints&&which>=0)AddMuscle(num_joints-1,which,0,10,boneconnect);
+ }
+}
+
+void Skeleton::DeleteJoint(int whichjoint)
+{
+ if(whichjoint<num_joints&&whichjoint>=0){
+ joints[whichjoint].velocity=joints[num_joints-1].velocity;
+ joints[whichjoint].position=joints[num_joints-1].position;
+ joints[whichjoint].oldposition=joints[num_joints-1].oldposition;
+ joints[whichjoint].hasparent=joints[num_joints-1].hasparent;
+ joints[whichjoint].parent=joints[num_joints-1].parent;
+ joints[whichjoint].length=joints[num_joints-1].length;
+ joints[whichjoint].locked=joints[num_joints-1].locked;
+ joints[whichjoint].modelnum=joints[num_joints-1].modelnum;
+ joints[whichjoint].visible=joints[num_joints-1].visible;
+
+ for(int i=0;i<num_muscles;i++){
+ while(muscles[i].parent1==&joints[whichjoint]&&i<num_muscles)DeleteMuscle(i);
+ while(muscles[i].parent2==&joints[whichjoint]&&i<num_muscles)DeleteMuscle(i);
+ }
+ for(int i=0;i<num_muscles;i++){
+ while(muscles[i].parent1==&joints[num_joints-1]&&i<num_muscles)muscles[i].parent1=&joints[whichjoint];
+ while(muscles[i].parent2==&joints[num_joints-1]&&i<num_muscles)muscles[i].parent2=&joints[whichjoint];
+ }
+ for(int i=0;i<num_joints;i++){
+ if(joints[i].parent==&joints[whichjoint])joints[i].hasparent=0;
+ }
+ for(int i=0;i<num_joints;i++){
+ if(joints[i].parent==&joints[num_joints-1])joints[i].parent=&joints[whichjoint];
+ }
+
+ num_joints--;
+ }
+}
+
+void Skeleton::DeleteMuscle(int whichmuscle)
+{
+ if(whichmuscle<num_muscles){
+ muscles[whichmuscle].minlength=muscles[num_muscles-1].minlength;
+ muscles[whichmuscle].maxlength=muscles[num_muscles-1].maxlength;
+ muscles[whichmuscle].strength=muscles[num_muscles-1].strength;
+ muscles[whichmuscle].parent1=muscles[num_muscles-1].parent1;
+ muscles[whichmuscle].parent2=muscles[num_muscles-1].parent2;
+ muscles[whichmuscle].length=muscles[num_muscles-1].length;
+ muscles[whichmuscle].visible=muscles[num_muscles-1].visible;
+ muscles[whichmuscle].type=muscles[num_muscles-1].type;
+ muscles[whichmuscle].targetlength=muscles[num_muscles-1].targetlength;
+
+ num_muscles--;
+ }
+}
+
+void Skeleton::SetJoint(float x, float y, float z, int which, int whichjoint)
+{
+ if(whichjoint<num_joints){
+ joints[whichjoint].velocity=0;
+ joints[whichjoint].position.x=x;
+ joints[whichjoint].position.y=y;
+ joints[whichjoint].position.z=z;
+
+ if(which>=num_joints||which<0)joints[whichjoint].hasparent=0;
+ if(which<num_joints&&which>=0){
+ joints[whichjoint].parent=&joints[which];
+ joints[whichjoint].hasparent=1;
+ joints[whichjoint].length=findDistance(&joints[whichjoint].position,&joints[whichjoint].parent->position);
+ }
+ }
+}
+
+void Skeleton::AddMuscle(int attach1,int attach2,float minlength,float maxlength,int type)
+{
+ if(num_muscles<max_muscles-1&&attach1<num_joints&&attach1>=0&&attach2<num_joints&&attach2>=0&&attach1!=attach2){
+ muscles[num_muscles].parent1=&joints[attach1];
+ muscles[num_muscles].parent2=&joints[attach2];
+ muscles[num_muscles].length=findDistance(&muscles[num_muscles].parent1->position,&muscles[num_muscles].parent2->position);
+ muscles[num_muscles].targetlength=findDistance(&muscles[num_muscles].parent1->position,&muscles[num_muscles].parent2->position);
+ muscles[num_muscles].strength=.7;
+ muscles[num_muscles].type=type;
+ muscles[num_muscles].minlength=minlength;
+ muscles[num_muscles].maxlength=maxlength;
+
+ num_muscles++;
+ }
+}
+
+void Skeleton::MusclesSet()
+{
+ for(int i=0;i<num_muscles;i++){
+ muscles[i].length=findDistance(&muscles[i].parent1->position,&muscles[i].parent2->position);
+ }
+}
+
+void Skeleton::DoBalance()
+{
+ /*XYZ newpoint;
+ newpoint=joints[0].position;
+ newpoint.x=(joints[2].position.x+joints[4].position.x)/2;
+ newpoint.z=(joints[2].position.z+joints[4].position.z)/2;
+ joints[0].velocity=joints[0].velocity+(newpoint-joints[0].position);
+ //Move child point to within certain distance of parent point
+ joints[0].position=newpoint;
+
+ MusclesSet();*/
+}
+
+void Skeleton::FindRotationMuscle(int which, int animation)
+{
+ static XYZ temppoint1,temppoint2,tempforward;
+ static float distance;
+
+ temppoint1=muscles[which].parent1->position;
+ temppoint2=muscles[which].parent2->position;
+ distance=sqrt((temppoint1.x-temppoint2.x)*(temppoint1.x-temppoint2.x)+(temppoint1.y-temppoint2.y)*(temppoint1.y-temppoint2.y)+(temppoint1.z-temppoint2.z)*(temppoint1.z-temppoint2.z));
+ if((temppoint1.y-temppoint2.y)<=distance)muscles[which].rotate2=asin((temppoint1.y-temppoint2.y)/distance);
+ if((temppoint1.y-temppoint2.y)>distance)muscles[which].rotate2=asin(1.f);
+ muscles[which].rotate2*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ distance=sqrt((temppoint1.x-temppoint2.x)*(temppoint1.x-temppoint2.x)+(temppoint1.y-temppoint2.y)*(temppoint1.y-temppoint2.y)+(temppoint1.z-temppoint2.z)*(temppoint1.z-temppoint2.z));
+ if((temppoint1.z-temppoint2.z)<=distance)muscles[which].rotate1=acos((temppoint1.z-temppoint2.z)/distance);
+ if((temppoint1.z-temppoint2.z)>distance)muscles[which].rotate1=acos(1.f);
+ muscles[which].rotate1*=360/6.28;
+ if(temppoint1.x>temppoint2.x)muscles[which].rotate1=360-muscles[which].rotate1;
+ if(!isnormal(muscles[which].rotate1))muscles[which].rotate1=0;
+ if(!isnormal(muscles[which].rotate2))muscles[which].rotate2=0;
+
+ if(muscles[which].parent1->label==head)tempforward=specialforward[0];
+ else if(muscles[which].parent1->label==rightshoulder||muscles[which].parent1->label==rightelbow||muscles[which].parent1->label==rightwrist||muscles[which].parent1->label==righthand)tempforward=specialforward[1];
+ else if(muscles[which].parent1->label==leftshoulder||muscles[which].parent1->label==leftelbow||muscles[which].parent1->label==leftwrist||muscles[which].parent1->label==lefthand)tempforward=specialforward[2];
+ else if(muscles[which].parent1->label==righthip||muscles[which].parent1->label==rightknee||muscles[which].parent1->label==rightankle||muscles[which].parent1->label==rightfoot)tempforward=specialforward[3];
+ else if(muscles[which].parent1->label==lefthip||muscles[which].parent1->label==leftknee||muscles[which].parent1->label==leftankle||muscles[which].parent1->label==leftfoot)tempforward=specialforward[4];
+ else if(!muscles[which].parent1->lower)tempforward=forward;
+ else if(muscles[which].parent1->lower)tempforward=lowforward;
+
+ if(animation==hanganim){
+ if(muscles[which].parent1->label==righthand||muscles[which].parent2->label==righthand){
+ tempforward=0;
+ tempforward.x=-1;
+ }
+ if(muscles[which].parent1->label==lefthand||muscles[which].parent2->label==lefthand){
+ tempforward=0;
+ tempforward.x=1;
+ }
+ }
+
+ if(free==0){
+ if(muscles[which].parent1->label==rightfoot||muscles[which].parent2->label==rightfoot){
+ tempforward.y-=.3;
+ }
+ if(muscles[which].parent1->label==leftfoot||muscles[which].parent2->label==leftfoot){
+ tempforward.y-=.3;
+ }
+ }
+
+
+ tempforward=DoRotation(tempforward,0,muscles[which].rotate1-90,0);
+ tempforward=DoRotation(tempforward,0,0,muscles[which].rotate2-90);
+ tempforward.y=0;
+ tempforward/=sqrt(tempforward.x*tempforward.x+tempforward.y*tempforward.y+tempforward.z*tempforward.z);
+ if(tempforward.z<=1&&tempforward.z>=-1)muscles[which].rotate3=acos(0-tempforward.z);
+ else muscles[which].rotate3=acos(-1.f);
+ muscles[which].rotate3*=360/6.28;
+ if(0>tempforward.x)muscles[which].rotate3=360-muscles[which].rotate3;
+ if(!isnormal(muscles[which].rotate3))muscles[which].rotate3=0;
+}
+
+void Animation::Load(char *filename, int aheight, int aattack)
+{
+ static FILE *tfile;
+ static int i,j;
+ static XYZ startoffset,endoffset;
+ static int howmany;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading animation...") + filename);
+
+ deallocate();
+
+ height=aheight;
+ attack=aattack;
+
+ if(visibleloading)pgame->LoadingScreen();
+
+ tfile=fopen( filename, "rb" );
+ if(tfile){
+ funpackf(tfile, "Bi Bi", &numframes, &joints);
+ /*
+ for(i = 0; i < joints; i++){
+ if(position[i])dealloc2(position[i]);
+ if(twist[i])dealloc2(twist[i]);
+ if(twist2[i])dealloc2(twist2[i]);
+ if(onground[i])dealloc2(onground[i]);
+ }*/
+ /*
+ if(position)dealloc2(position);
+ if(twist)dealloc2(twist);
+ if(twist2)dealloc2(twist2);
+ if(speed)dealloc2(speed);
+ if(onground)dealloc2(onground);
+ if(forward)dealloc2(forward);
+ if(weapontarget)dealloc2(weapontarget);
+ if(label)dealloc2(label);*/
+
+ position=(XYZ**)malloc(sizeof(XYZ*)*joints);
+ for(i = 0; i < joints; i++)
+ position[i] = (XYZ*)malloc(sizeof(XYZ)*numframes);
+
+ twist=(float**)malloc(sizeof(float*)*joints);
+ for(i = 0; i < joints; i++)
+ twist[i] = (float*)malloc(sizeof(float)*numframes);
+
+ twist2=(float**)malloc(sizeof(float*)*joints);
+ for(i = 0; i < joints; i++)
+ twist2[i] = (float*)malloc(sizeof(float)*numframes);
+
+ speed = (float*)malloc(sizeof(float)*numframes);
+
+ onground=(bool**)malloc(sizeof(bool*)*joints);
+ for(i = 0; i < joints; i++)
+ onground[i] =(bool*)malloc(sizeof(bool)*numframes);
+
+ forward = (XYZ*)malloc(sizeof(XYZ)*numframes);
+ weapontarget = (XYZ*)malloc(sizeof(XYZ)*numframes);
+ label = (int*)malloc(sizeof(int)*numframes);
+
+ /*position = new XYZ[joints][numframes];
+ twist = new float[joints][numframes];
+ twist2 = new float[joints][numframes];
+ speed = new float[numframes];
+ onground = new bool[joints][numframes];
+ forward = new XYZ[numframes];
+ label = new int[numframes];*/
+
+ for(i=0;i<numframes;i++){
+ for(j=0;j<joints;j++){
+ funpackf(tfile, "Bf Bf Bf", &position[j][i].x,&position[j][i].y,&position[j][i].z);
+ }
+ for(j=0;j<joints;j++){
+ funpackf(tfile, "Bf", &twist[j][i]);
+ }
+ for(j=0;j<joints;j++){
+ funpackf(tfile, "Bb", &onground[j][i]);
+ }
+ funpackf(tfile, "Bf", &speed[i]);
+ }
+ for(i=0;i<numframes;i++){
+ for(j=0;j<joints;j++){
+ funpackf(tfile, "Bf", &twist2[j][i]);
+ }
+ }
+ for(i=0;i<numframes;i++){
+ funpackf(tfile, "Bf", &label[i]);
+ }
+ funpackf(tfile, "Bi", &weapontargetnum);
+ for(i=0;i<numframes;i++){
+ funpackf(tfile, "Bf Bf Bf", &weapontarget[i].x,&weapontarget[i].y,&weapontarget[i].z);
+ }
+
+ fclose(tfile);
+ }
+
+ startoffset=0;
+ endoffset=0;
+ howmany=0;
+ for(j=0;j<joints;j++){
+ if(position[j][0].y<1)
+ startoffset+=position[j][0];
+ if(position[j][numframes-1].y<1)
+ endoffset+=position[j][numframes-1];
+ howmany++;
+ }
+ startoffset/=howmany;
+ endoffset/=howmany;
+ offset=endoffset;
+ offset.y=0;
+}
+
+
+void Animation::Move(XYZ how)
+{
+ static int i,j,joints;
+ for(i=0;i<numframes;i++){
+ for(j=0;j<joints;j++){
+ position[j][i]=0;
+ }
+ }
+}
+
+void Skeleton::Load(char *filename,char *lowfilename,char *clothesfilename, char *modelfilename, char *model2filename, char *model3filename, char *model4filename, char *model5filename, char *model6filename, char *model7filename, char *modellowfilename, char *modelclothesfilename, bool aclothes)
+{
+ static GLfloat M[16];
+ static int parentID;
+ static FILE *tfile;
+ static float lSize;
+ static int i,j,tempmuscle;
+ int newload;
+ int edit;
+
+ LOGFUNC;
+
+ newload=0;
+
+ num_models=7;
+
+ clothes=aclothes;
+
+ for(i=0;i<num_models;i++){
+ if(i==0)model[i].loadnotex(modelfilename);
+ if(i==1)model[i].loadnotex(model2filename);
+ if(i==2)model[i].loadnotex(model3filename);
+ if(i==3)model[i].loadnotex(model4filename);
+ if(i==4)model[i].loadnotex(model5filename);
+ if(i==5)model[i].loadnotex(model6filename);
+ if(i==6)model[i].loadnotex(model7filename);
+ model[i].Rotate(180,0,0);
+ model[i].Scale(.04,.04,.04);
+ model[i].CalculateNormals(0);
+ }
+
+ drawmodel.load(modelfilename,0);
+ drawmodel.Rotate(180,0,0);
+ drawmodel.Scale(.04,.04,.04);
+ drawmodel.FlipTexCoords();
+ if(tutoriallevel==1&&id!=0)drawmodel.UniformTexCoords();
+ if(tutoriallevel==1&&id!=0)drawmodel.ScaleTexCoords(0.1);
+ drawmodel.CalculateNormals(0);
+
+ modellow.loadnotex(modellowfilename);
+ modellow.Rotate(180,0,0);
+ modellow.Scale(.04,.04,.04);
+ modellow.CalculateNormals(0);
+
+ drawmodellow.load(modellowfilename,0);
+ drawmodellow.Rotate(180,0,0);
+ drawmodellow.Scale(.04,.04,.04);
+ drawmodellow.FlipTexCoords();
+ if(tutoriallevel==1&&id!=0)drawmodellow.UniformTexCoords();
+ if(tutoriallevel==1&&id!=0)drawmodellow.ScaleTexCoords(0.1);
+ drawmodellow.CalculateNormals(0);
+
+ if(clothes){
+ modelclothes.loadnotex(modelclothesfilename);
+ modelclothes.Rotate(180,0,0);
+ modelclothes.Scale(.041,.04,.041);
+ modelclothes.CalculateNormals(0);
+
+ drawmodelclothes.load(modelclothesfilename,0);
+ drawmodelclothes.Rotate(180,0,0);
+ drawmodelclothes.Scale(.04,.04,.04);
+ drawmodelclothes.FlipTexCoords();
+ drawmodelclothes.CalculateNormals(0);
+ }
+
+ tfile=fopen( filename, "rb" );
+ if(1){
+ funpackf(tfile, "Bi", &num_joints);
+ //joints.resize(num_joints);
+ if(joints) delete [] joints; //dealloc2(joints);
+ joints=(Joint*)new Joint[num_joints]; //malloc(sizeof(Joint)*num_joints);
+
+ for(i=0;i<num_joints;i++){
+ funpackf(tfile, "Bf Bf Bf Bf Bf", &joints[i].position.x, &joints[i].position.y, &joints[i].position.z, &joints[i].length,&joints[i].mass);
+ funpackf(tfile, "Bb Bb", &joints[i].hasparent,&joints[i].locked);
+ funpackf(tfile, "Bi", &joints[i].modelnum);
+ funpackf(tfile, "Bb Bb", &joints[i].visible,&joints[i].sametwist);
+ funpackf(tfile, "Bi Bi", &joints[i].label,&joints[i].hasgun);
+ funpackf(tfile, "Bb", &joints[i].lower);
+ funpackf(tfile, "Bi", &parentID);
+ if(joints[i].hasparent)joints[i].parent=&joints[parentID];
+ joints[i].velocity=0;
+ joints[i].oldposition=joints[i].position;
+ }
+ tempmuscle=num_muscles;
+ funpackf(tfile, "Bi", &num_muscles);
+ //muscles.clear();
+ if(muscles) delete [] muscles; //dealloc2(muscles);
+ muscles=(Muscle*)new Muscle[num_muscles]; //malloc(sizeof(Muscle)*num_muscles);
+ newload=1;
+ for(i=0;i<num_muscles;i++){
+ tempmuscle=muscles[i].numvertices;
+ funpackf(tfile, "Bf Bf Bf Bf Bf Bi Bi", &muscles[i].length, &muscles[i].targetlength,&muscles[i].minlength, &muscles[i].maxlength,&muscles[i].strength,&muscles[i].type,&muscles[i].numvertices);
+ //muscles[i].vertices.clear();
+ //muscles[i].vertices.resize(muscles[i].numvertices);
+ //if(muscles[i].vertices)dealloc2(muscles[i].vertices);
+ muscles[i].vertices=(int*)malloc(sizeof(int)*muscles[i].numvertices);
+
+ edit=0;
+ for(j=0;j<muscles[i].numvertices-edit;j++){
+ funpackf(tfile, "Bi", &muscles[i].vertices[j+edit]);
+ if(muscles[i].vertices[j+edit]>=model[0].vertexNum){
+ muscles[i].numvertices--;
+ edit--;
+ }
+ }
+ funpackf(tfile, "Bb Bi", &muscles[i].visible, &parentID);
+ muscles[i].parent1=&joints[parentID];
+ funpackf(tfile, "Bi", &parentID);
+ muscles[i].parent2=&joints[parentID];
+ }
+ for(j=0;j<3;j++){
+ funpackf(tfile, "Bi", &forwardjoints[j]);
+ }
+ for(j=0;j<3;j++){
+ funpackf(tfile, "Bi", &lowforwardjoints[j]);
+ }
+ for(j=0;j<num_muscles;j++){
+ for(i=0;i<muscles[j].numvertices;i++){
+ for(int k=0;k<num_models;k++){
+ if(muscles[j].numvertices&&muscles[j].vertices[i]<model[k].vertexNum)model[k].owner[muscles[j].vertices[i]]=j;
+ }
+ }
+ }
+ FindForwards();
+ for(i=0;i<num_joints;i++){
+ joints[i].startpos=joints[i].position;
+ }
+ for(i=0;i<num_muscles;i++){
+ FindRotationMuscle(i,-1);
+ }
+ for(int k=0;k<num_models;k++){
+ for(i=0;i<model[k].vertexNum;i++){
+ model[k].vertex[i]=model[k].vertex[i]-(muscles[model[k].owner[i]].parent1->position+muscles[model[k].owner[i]].parent2->position)/2;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ glRotatef(muscles[model[k].owner[i]].rotate3,0,1,0);
+ glRotatef(muscles[model[k].owner[i]].rotate2-90,0,0,1);
+ glRotatef(muscles[model[k].owner[i]].rotate1-90,0,1,0);
+ glTranslatef(model[k].vertex[i].x,model[k].vertex[i].y,model[k].vertex[i].z);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ model[k].vertex[i].x=M[12]*1;
+ model[k].vertex[i].y=M[13]*1;
+ model[k].vertex[i].z=M[14]*1;
+ glPopMatrix();
+ }
+ model[k].CalculateNormals(0);
+ }
+ }
+ fclose(tfile);
+
+ tfile=fopen( lowfilename, "rb" );
+ if(1){
+ lSize=sizeof(num_joints);
+ fseek ( tfile, lSize, SEEK_CUR);
+ //joints = new Joint[num_joints];
+ //jointlabels = new int[num_joints];
+ for(i=0;i<num_joints;i++){
+ lSize=sizeof(XYZ);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ if(joints[i].hasparent)joints[i].parent=&joints[parentID];
+ joints[i].velocity=0;
+ joints[i].oldposition=joints[i].position;
+ }
+ funpackf(tfile, "Bi", &num_muscles);
+ //muscles = new Muscle[num_muscles];
+ for(i=0;i<num_muscles;i++){
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ tempmuscle=muscles[i].numverticeslow;
+ funpackf(tfile, "Bi", &muscles[i].numverticeslow);
+ if(muscles[i].numverticeslow){
+ //muscles[i].verticeslow.clear();
+ //muscles[i].verticeslow.resize(muscles[i].numverticeslow);
+ //if(muscles[i].verticeslow)dealloc2(muscles[i].verticeslow);
+ muscles[i].verticeslow=(int*)malloc(sizeof(int)*muscles[i].numverticeslow);
+ edit=0;
+ for(j=0;j<muscles[i].numverticeslow-edit;j++){
+ funpackf(tfile, "Bi", &muscles[i].verticeslow[j+edit]);
+ if(muscles[i].verticeslow[j+edit]>=modellow.vertexNum){
+ muscles[i].numverticeslow--;
+ edit--;
+ }
+ }
+
+
+ }
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ fseek ( tfile, lSize, SEEK_CUR);
+ }
+ lSize=sizeof(int);
+ for(j=0;j<num_muscles;j++){
+ for(i=0;i<muscles[j].numverticeslow;i++){
+ if(muscles[j].numverticeslow&&muscles[j].verticeslow[i]<modellow.vertexNum)modellow.owner[muscles[j].verticeslow[i]]=j;
+ }
+ }
+ /*FindForwards();
+ for(i=0;i<num_joints;i++){
+ joints[i].startpos=joints[i].position;
+ }
+ for(i=0;i<num_muscles;i++){
+ FindRotationMuscle(i,-1);
+ }*/
+ for(i=0;i<modellow.vertexNum;i++){
+ modellow.vertex[i]=modellow.vertex[i]-(muscles[modellow.owner[i]].parent1->position+muscles[modellow.owner[i]].parent2->position)/2;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ glRotatef(muscles[modellow.owner[i]].rotate3,0,1,0);
+ glRotatef(muscles[modellow.owner[i]].rotate2-90,0,0,1);
+ glRotatef(muscles[modellow.owner[i]].rotate1-90,0,1,0);
+ glTranslatef(modellow.vertex[i].x,modellow.vertex[i].y,modellow.vertex[i].z);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ modellow.vertex[i].x=M[12];
+ modellow.vertex[i].y=M[13];
+ modellow.vertex[i].z=M[14];
+ glPopMatrix();
+ }
+ modellow.CalculateNormals(0);
+ }
+
+ if(clothes){
+ tfile=fopen( clothesfilename, "rb" );
+ lSize=sizeof(num_joints);
+ fseek ( tfile, lSize, SEEK_CUR);
+ //joints = new Joint[num_joints];
+ //jointlabels = new int[num_joints];
+ for(i=0;i<num_joints;i++){
+ lSize=sizeof(XYZ);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ if(joints[i].hasparent)joints[i].parent=&joints[parentID];
+ joints[i].velocity=0;
+ joints[i].oldposition=joints[i].position;
+ }
+ funpackf(tfile, "Bi", &num_muscles);
+ //muscles = new Muscle[num_muscles];
+ for(i=0;i<num_muscles;i++){
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(float);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ tempmuscle=muscles[i].numverticesclothes;
+ funpackf(tfile, "Bi", &muscles[i].numverticesclothes);
+ if(muscles[i].numverticesclothes){
+ //muscles[i].verticesclothes.clear();
+ //muscles[i].verticesclothes.resize(muscles[i].numverticesclothes);
+ //if(muscles[i].verticesclothes)dealloc2(muscles[i].verticesclothes);
+ muscles[i].verticesclothes=(int*)malloc(sizeof(int)*muscles[i].numverticesclothes);
+ edit=0;
+ for(j=0;j<muscles[i].numverticesclothes-edit;j++){
+ funpackf(tfile, "Bi", &muscles[i].verticesclothes[j+edit]);
+ if(muscles[i].verticesclothes[j+edit]>=modelclothes.vertexNum){
+ muscles[i].numverticesclothes--;
+ edit--;
+ }
+ }
+ }
+ lSize=sizeof(bool);
+ fseek ( tfile, lSize, SEEK_CUR);
+ lSize=sizeof(int);
+ fseek ( tfile, lSize, SEEK_CUR);
+ fseek ( tfile, lSize, SEEK_CUR);
+ }
+ lSize=sizeof(int);
+ for(j=0;j<num_muscles;j++){
+ for(i=0;i<muscles[j].numverticesclothes;i++){
+ if(muscles[j].numverticesclothes&&muscles[j].verticesclothes[i]<modelclothes.vertexNum)modelclothes.owner[muscles[j].verticesclothes[i]]=j;
+ }
+ }
+ /*FindForwards();
+ for(i=0;i<num_joints;i++){
+ joints[i].startpos=joints[i].position;
+ }
+ for(i=0;i<num_muscles;i++){
+ FindRotationMuscle(i,-1);
+ }*/
+ for(i=0;i<modelclothes.vertexNum;i++){
+ modelclothes.vertex[i]=modelclothes.vertex[i]-(muscles[modelclothes.owner[i]].parent1->position+muscles[modelclothes.owner[i]].parent2->position)/2;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ glRotatef(muscles[modelclothes.owner[i]].rotate3,0,1,0);
+ glRotatef(muscles[modelclothes.owner[i]].rotate2-90,0,0,1);
+ glRotatef(muscles[modelclothes.owner[i]].rotate1-90,0,1,0);
+ glTranslatef(modelclothes.vertex[i].x,modelclothes.vertex[i].y,modelclothes.vertex[i].z);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ modelclothes.vertex[i].x=M[12];
+ modelclothes.vertex[i].y=M[13];
+ modelclothes.vertex[i].z=M[14];
+ glPopMatrix();
+ }
+ modelclothes.CalculateNormals(0);
+ }
+ fclose(tfile);
+
+ for(i=0;i<num_joints;i++){
+ for(j=0;j<num_joints;j++){
+ if(joints[i].label==j)jointlabels[j]=i;
+ }
+ }
+
+ free=0;
+}
+
+Animation::Animation()
+{
+ numframes = 0;
+ height = 0;
+ attack = 0;
+ joints = 0;
+ weapontargetnum = 0;
+
+ position=0;
+ twist=0;
+ twist2=0;
+ speed=0;
+ onground=0;
+ forward=0;
+ label=0;
+ weapontarget=0;
+}
+
+Animation::~Animation()
+{
+ deallocate();
+}
+
+void Animation::deallocate()
+{
+ int i = 0;
+
+ if(position)
+ {
+ for(i = 0; i < joints; i++)
+ dealloc2(position[i]);
+
+ dealloc2(position);
+ }
+ position = 0;
+
+ if(twist)
+ {
+ for(i = 0; i < joints; i++)
+ dealloc2(twist[i]);
+
+ dealloc2(twist);
+ }
+ twist = 0;
+
+ if(twist2)
+ {
+ for(i = 0; i < joints; i++)
+ dealloc2(twist2[i]);
+
+ dealloc2(twist2);
+ }
+ twist2 = 0;
+
+ if(onground)
+ {
+ for(i = 0; i < joints; i++)
+ dealloc2(onground[i]);
+
+ dealloc2(onground);
+ }
+ onground = 0;
+
+ if(speed)dealloc2(speed);
+ speed = 0;
+
+ if(forward)dealloc2(forward);
+ forward = 0;
+
+ if(weapontarget)dealloc2(weapontarget);
+ weapontarget = 0;
+
+ if(label)dealloc2(label);
+ label = 0;
+
+ joints = 0;
+}
+
+Skeleton::Skeleton()
+{
+ num_joints = 0;
+
+ num_muscles = 0;
+
+ selected = 0;
+
+ memset(forwardjoints, 0, sizeof(forwardjoints));
+ // XYZ forward;
+
+ id = 0;
+
+ memset(lowforwardjoints, 0, sizeof(lowforwardjoints));
+ // XYZ lowforward;
+
+ // XYZ specialforward[5];
+ memset(jointlabels, 0, sizeof(jointlabels));
+
+ // Model model[7];
+ // Model modellow;
+ // Model modelclothes;
+ num_models = 0;
+
+ // Model drawmodel;
+ // Model drawmodellow;
+ // Model drawmodelclothes;
+
+ clothes = 0;
+ spinny = 0;
+
+ memset(skinText, 0, sizeof(skinText));
+ skinsize = 0;
+
+ checkdelay = 0;
+
+ longdead = 0;
+ broken = 0;
+
+ free = 0;
+ oldfree = 0;
+ freetime = 0;
+ freefall = 0;
+
+ joints=0;
+ muscles=0;
+}
+
+Skeleton::~Skeleton()
+{
+ if (muscles)
+ {
+ delete [] muscles;
+ }
+ muscles = 0;
+
+ if (joints)
+ {
+ delete [] joints;
+ }
+ joints = 0;
+}
+
+Muscle::Muscle()
+{
+ vertices=0;
+ verticeslow=0;
+ verticesclothes=0;
+
+ numvertices = 0;
+ numverticeslow = 0;
+ numverticesclothes = 0;
+ length = 0;
+ targetlength = 0;
+ parent1 = 0;
+ parent2 = 0;
+ maxlength = 0;
+ minlength = 0;
+ type = 0;
+ visible = 0;
+ rotate1 = 0,rotate2 = 0,rotate3 = 0;
+ lastrotate1 = 0,lastrotate2 = 0,lastrotate3 = 0;
+ oldrotate1 = 0,oldrotate2 = 0,oldrotate3 = 0;
+ newrotate1 = 0,newrotate2 = 0,newrotate3 = 0;
+
+ strength = 0;
+}
+
+Muscle::~Muscle()
+{
+ dealloc2(vertices);
+ dealloc2(verticeslow);
+ dealloc2(verticesclothes);
+}
+
+Animation & Animation::operator = (const Animation & ani)
+{
+ int i = 0;
+
+ bool allocate = true;
+
+ allocate = ((ani.numframes != numframes) || (ani.joints != joints));
+
+ if (allocate) deallocate();
+
+ numframes = ani.numframes;
+ height = ani.height;
+ attack = ani.attack;
+ joints = ani.joints;
+ weapontargetnum = ani.weapontargetnum;
+
+ if (allocate) position=(XYZ**)malloc(sizeof(XYZ*)*ani.joints);
+ for(i = 0; i < ani.joints; i++)
+ {
+ if (allocate) position[i] = (XYZ*)malloc(sizeof(XYZ)*ani.numframes);
+ memcpy(position[i], ani.position[i], sizeof(XYZ)*ani.numframes);
+ }
+
+ if (allocate) twist=(float**)malloc(sizeof(float*)*ani.joints);
+ for(i = 0; i < ani.joints; i++)
+ {
+ if (allocate) twist[i] = (float*)malloc(sizeof(float)*ani.numframes);
+ memcpy(twist[i], ani.twist[i], sizeof(float)*ani.numframes);
+ }
+
+ if (allocate) twist2=(float**)malloc(sizeof(float*)*ani.joints);
+ for(i = 0; i < ani.joints; i++)
+ {
+ if (allocate) twist2[i] = (float*)malloc(sizeof(float)*ani.numframes);
+ memcpy(twist2[i], ani.twist2[i], sizeof(float)*ani.numframes);
+ }
+
+ if (allocate) speed = (float*)malloc(sizeof(float)*ani.numframes);
+ memcpy(speed, ani.speed, sizeof(float)*ani.numframes);
+
+ if (allocate) onground=(bool**)malloc(sizeof(bool*)*ani.joints);
+ for(i = 0; i < ani.joints; i++)
+ {
+ if (allocate) onground[i] =(bool*)malloc(sizeof(bool)*ani.numframes);
+ memcpy(onground[i], ani.onground[i], sizeof(bool)*ani.numframes);
+ }
+
+ if (allocate) forward = (XYZ*)malloc(sizeof(XYZ)*ani.numframes);
+ memcpy(forward, ani.forward, sizeof(XYZ)*ani.numframes);
+
+ if (allocate) weapontarget = (XYZ*)malloc(sizeof(XYZ)*ani.numframes);
+ memcpy(weapontarget, ani.weapontarget, sizeof(XYZ)*ani.numframes);
+
+ if (allocate) label = (int*)malloc(sizeof(int)*ani.numframes);
+ memcpy(label, ani.label, sizeof(int)*ani.numframes);
+
+ return (*this);
+}
--- /dev/null
+#ifndef _SKELETON_H_
+#define _SKELETON_H_
+
+#include "Models.h"
+#include "Quaternions.h"
+#include "Constants.h"
+
+
+/**> HEADER FILES <**/
+#include "gl.h"
+#include "Quaternions.h"
+#include "fmod.h"
+#include "objects.h"
+#include "Sprites.h"
+#include "binio.h"
+
+#define neutral 0
+#define normalattack 1
+#define reversed 2
+#define reversal 3
+#define lowheight 0
+#define middleheight 1
+#define highheight 2
+
+class Joint
+{
+public:
+ XYZ position;
+ XYZ oldposition;
+ XYZ realoldposition;
+ XYZ velocity;
+ XYZ oldvelocity;
+ XYZ startpos;
+ float blurred;
+ float length;
+ float mass;
+ bool lower;
+ bool hasparent;
+ bool locked;
+ int modelnum;
+ bool visible;
+ Joint* parent;
+ bool sametwist;
+ int label;
+ int hasgun;
+ float delay;
+ XYZ velchange;
+
+ Joint()
+ {
+ blurred = 0;
+ length = 0;
+ mass = 0;
+ lower = 0;
+ hasparent = 0;
+ locked = 0;
+ modelnum = 0;
+ visible = 0;
+ parent = 0;
+ sametwist = 0;
+ label = 0;
+ hasgun = 0;
+ delay = 0;
+ }
+
+ void DoConstraint();
+};
+
+class Muscle
+{
+public:
+ int numvertices;
+ int* vertices;
+ int numverticeslow;
+ int* verticeslow;
+ int numverticesclothes;
+ int* verticesclothes;
+ float length;
+ float targetlength;
+ Joint* parent1;
+ Joint* parent2;
+ float maxlength;
+ float minlength;
+ int type;
+ bool visible;
+ void DoConstraint(bool spinny);
+ float rotate1,rotate2,rotate3;
+ float lastrotate1,lastrotate2,lastrotate3;
+ float oldrotate1,oldrotate2,oldrotate3;
+ float newrotate1,newrotate2,newrotate3;
+
+ float strength;
+
+ ~Muscle();
+ Muscle();
+};
+
+class Animation
+{
+public:
+ int numframes;
+ int height;
+ int attack;
+ int joints;
+ int weapontargetnum;
+
+ XYZ** position;
+ float** twist;
+ float** twist2;
+ float* speed;
+ bool** onground;
+ XYZ* forward;
+ int* label;
+ XYZ* weapontarget;
+
+
+ XYZ offset;
+
+ Animation();
+
+ ~Animation();
+
+ Animation & operator = (const Animation & ani);
+
+ void Load(char *fileName, int aheight, int aattack);
+ void Move(XYZ how);
+
+protected:
+ void deallocate();
+};
+
+
+class Skeleton
+{
+public:
+ int num_joints;
+ //Joint joints[max_joints];
+ //Joint *joints;
+ Joint* joints;
+
+ int num_muscles;
+ //Muscle muscles[max_muscles];
+ //Muscle *muscles;
+ Muscle* muscles;
+
+ int selected;
+
+ int forwardjoints[3];
+ XYZ forward;
+
+ int id;
+
+ int lowforwardjoints[3];
+ XYZ lowforward;
+
+ XYZ specialforward[5];
+ int jointlabels[max_joints];
+
+ Model model[7];
+ Model modellow;
+ Model modelclothes;
+ int num_models;
+
+ Model drawmodel;
+ Model drawmodellow;
+ Model drawmodelclothes;
+
+ bool clothes;
+ bool spinny;
+
+ GLubyte skinText[512*512*3];
+ int skinsize;
+
+ float checkdelay;
+
+ float longdead;
+ bool broken;
+
+ int free;
+ int oldfree;
+ float freetime;
+ bool freefall;
+
+ void FindForwards();
+ void FindForwardsfirst();
+ float DoConstraints(XYZ *coords,float *scale);
+ void DoGravity(float *scale);
+ void DoBalance();
+ void MusclesSet();
+ void Draw(int muscleview);
+ void AddJoint(float x, float y, float z, int which);
+ void SetJoint(float x, float y, float z, int which, int whichjoint);
+ void DeleteJoint(int whichjoint);
+ void AddMuscle(int attach1,int attach2,float maxlength,float minlength,int type);
+ void DeleteMuscle(int whichmuscle);
+ void FindRotationJoint(int which);
+ void FindRotationJointSameTwist(int which);
+ void FindRotationMuscle(int which, int animation);
+ void Load(char *fileName,char *lowfileName,char *clothesfileName,char *modelfileName,char *model2fileName,char *model3fileName,char *model4fileName,char *model5fileNamee,char *model6fileName,char *model7fileName,char *modellowfileName,char *modelclothesfileName, bool aclothes);
+
+ Skeleton();
+
+ ~Skeleton();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "skybox.h"
+#include "Game.h"
+
+extern float viewdistance;
+extern int detail;
+extern bool trilinear;
+extern float blurness;
+extern int environment;
+extern TGAImageRec texture;
+extern bool skyboxtexture;
+extern float skyboxr;
+extern float skyboxg;
+extern float skyboxb;
+extern int tutoriallevel;
+
+bool SkyBox::load( char *ffront,char *fleft,char *fback,char *fright,char *fup,char *fdown,char *fcloud,char *freflect)
+{
+/* static GLuint type;
+ unsigned char fileNamep[256];
+*/
+ LOGFUNC;
+
+ //front
+ Game::LoadTexture(ffront, &front, true, false);
+ //left
+ Game::LoadTexture(fleft, &left, true, false);
+ //back
+ Game::LoadTexture(fback, &back, true, false);
+ //right
+ Game::LoadTexture(fright, &right, true, false);
+ //up
+ Game::LoadTexture(fup, &up, true, false);
+ //down
+ Game::LoadTexture(fdown, &down, true, false);
+ //cloud
+ Game::LoadTexture(fcloud, &cloud, true, false);
+ //reflect
+ Game::LoadTexture(freflect, &reflect, true, false);
+/*
+ //front
+ CopyCStringToPascal(ffront,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!front)glGenTextures( 1, &front );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, front);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //left
+ CopyCStringToPascal(fleft,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!left)glGenTextures( 1, &left );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, left);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //back
+ CopyCStringToPascal(fback,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!back)glGenTextures( 1, &back );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, back);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //right
+ CopyCStringToPascal(fright,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!right)glGenTextures( 1, &right );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, right);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //up
+ CopyCStringToPascal(fup,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!up)glGenTextures( 1, &up );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, up);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //down
+ CopyCStringToPascal(fdown,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!down)glGenTextures( 1, &down );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, down);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //cloud
+ CopyCStringToPascal(fcloud,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!cloud)glGenTextures( 1, &cloud );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, cloud);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+
+ //up
+ CopyCStringToPascal(freflect,fileNamep);
+ upload_image( fileNamep ,0);
+ if(1==1){
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!reflect)glGenTextures( 1, &reflect );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, reflect);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ if(trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ if(!trilinear)glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+
+ }
+*/
+ return true;
+}
+
+void SkyBox::draw()
+{
+ static float size=viewdistance/4;
+ glPushMatrix();
+ static GLfloat M[16];
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ M[12]=0;
+ M[13]=0;
+ M[14]=0;
+ glLoadMatrixf(M);
+ //if(environment==2)glTranslatef(0,blurness*viewdistance/1000,0);
+ if(environment==2)glScalef(1+blurness/1000,1,1+blurness/1000);
+ if(environment!=2)glColor3f(.85*skyboxr,.85*skyboxg,.95*skyboxb);
+ else glColor3f(1*skyboxr,.95*skyboxg,.95*skyboxb);
+
+ if(!skyboxtexture){
+ glDisable(GL_TEXTURE_2D);
+ glColor3f(skyboxr*.8,skyboxg*.8,skyboxb*.8);
+ }
+ glDepthMask(0);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ // glActiveTextureARB(GL_TEXTURE0_ARB);
+ if(skyboxtexture)glEnable(GL_TEXTURE_2D);
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glBindTexture(GL_TEXTURE_2D, front);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( 0.0f, 0.0f, -1);
+ glTexCoord2f(0, 0); glVertex3f(-size, -size, size);
+ glTexCoord2f(1, 0); glVertex3f( size, -size, size);
+ glTexCoord2f(1, 1); glVertex3f( size, size, size);
+ glTexCoord2f(0, 1); glVertex3f(-size, size, size);
+ glEnd();
+ glBindTexture(GL_TEXTURE_2D, back);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( 0.0f, 0.0f, 1);
+ glTexCoord2f(1, 0); glVertex3f(-size, -size, -size);
+ glTexCoord2f(1, 1); glVertex3f(-size, size, -size);
+ glTexCoord2f(0, 1); glVertex3f( size, size, -size);
+ glTexCoord2f(0, 0); glVertex3f( size, -size, -size);
+ glEnd();
+ glBindTexture(GL_TEXTURE_2D, up);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( 0.0f, -1.0f, 0);
+ glTexCoord2f(0, 1); glVertex3f(-size, size, -size);
+ glTexCoord2f(0, 0); glVertex3f(-size, size, size);
+ glTexCoord2f(1, 0); glVertex3f( size, size, size);
+ glTexCoord2f(1, 1); glVertex3f( size, size, -size);
+ glEnd();
+ //if(detail!=0){
+ glBindTexture(GL_TEXTURE_2D, down);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( 0.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 0); glVertex3f(-size, -size, -size);
+ glTexCoord2f(1, 0); glVertex3f( size, -size, -size);
+ glTexCoord2f(1, 1); glVertex3f( size, -size, size);
+ glTexCoord2f(0, 1); glVertex3f(-size, -size, size);
+ glEnd();
+ //}
+ glBindTexture(GL_TEXTURE_2D, right);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( -1.0f, 0.0f, 0);
+ glTexCoord2f(1, 0); glVertex3f( size, -size, -size);
+ glTexCoord2f(1, 1); glVertex3f( size, size, -size);
+ glTexCoord2f(0, 1); glVertex3f( size, size, size);
+ glTexCoord2f(0, 0); glVertex3f( size, -size, size);
+ glEnd();
+ glBindTexture(GL_TEXTURE_2D, left);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glBegin(GL_QUADS);
+ glNormal3f( 1.0f, 0.0f, 0);
+ glTexCoord2f(0, 0); glVertex3f(-size, -size, -size);
+ glTexCoord2f(1, 0); glVertex3f(-size, -size, size);
+ glTexCoord2f(1, 1); glVertex3f(-size, size, size);
+ glTexCoord2f(0, 1); glVertex3f(-size, size, -size);
+ glEnd();
+ /*
+ glEnable(GL_BLEND);
+ glColor4f(1,1,1,1);
+ glBindTexture(GL_TEXTURE_2D, cloud);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glBegin(GL_QUADS);
+ glNormal3f( 0.0f, -1.0f, 0);
+ glTexCoord2f(0, (1+cloudmove)*30); glVertex3f(-size, size/200, -size);
+ glTexCoord2f(0, 0); glVertex3f(-size, size/200, size);
+ glTexCoord2f((1+cloudmove)*30, 0); glVertex3f( size, size/200, size);
+ glTexCoord2f((1+cloudmove)*30, (1+cloudmove)*30); glVertex3f( size, size/200, -size);
+ glEnd();
+ glDisable(GL_BLEND);*/
+ glEnable(GL_CULL_FACE);
+ glDepthMask(1);
+ glPopMatrix();
+}
+
+SkyBox::SkyBox()
+{
+ front = 0,left = 0,back = 0,right = 0,up = 0,down = 0,cloud = 0,reflect = 0;
+ cloudmove = 0;
+}
+SkyBox::~SkyBox()
+{
+ if (front) glDeleteTextures( 1, (const unsigned long *)&front );
+ if (left) glDeleteTextures( 1, (const unsigned long *)&left );
+ if (back) glDeleteTextures( 1, (const unsigned long *)&back );
+ if (right) glDeleteTextures( 1, (const unsigned long *)&right );
+ if (up) glDeleteTextures( 1, (const unsigned long *)&up );
+ if (down) glDeleteTextures( 1, (const unsigned long *)&down );
+ if (cloud) glDeleteTextures( 1, (const unsigned long *)&cloud );
+ if (reflect) glDeleteTextures( 1, (const unsigned long *)&reflect );
+};
--- /dev/null
+#ifndef _SKYBOX_H_
+#define _SKYBOX_H_
+
+#include "Quaternions.h"
+#include "TGALoader.h"
+#include "Quaternions.h"
+#include "gl.h"
+
+class SkyBox{
+public:
+ GLuint front,left,back,right,up,down,cloud,reflect;
+ float cloudmove;
+
+ bool load(char *ffront,char *fleft,char *fback,char *fright,char *fup,char *fdown,char *fcloud,char *freflect);
+ void draw();
+
+ SkyBox();
+ ~SkyBox();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "Sprites.h"
+#include "Person.h"
+extern XYZ viewer;
+extern float viewdistance;
+extern float fadestart;
+extern int environment;
+extern float texscale;
+extern Light light;
+extern float multiplier;
+extern float gravity;
+extern Terrain terrain;
+extern Objects objects;
+extern int detail;
+extern XYZ viewerfacing;
+extern float terraindetail;
+extern int bloodtoggle;
+extern XYZ windvector;
+extern int numplayers;
+extern Person player[maxplayers];
+//Functions
+
+void Sprites::Draw()
+{
+ static int i,j,k;
+ static float M[16];
+ static XYZ point;
+ static float distancemult;
+ static int lasttype;
+ static int lastspecial;
+ static int whichpatchx,whichpatchz;
+ static XYZ start,end,colpoint;
+ static bool check;
+ static bool blend;
+ static float tempmult;
+ static XYZ difference;
+ static float lightcolor[3];
+ static float viewdistsquared=viewdistance*viewdistance;
+ static XYZ tempviewer;
+
+ tempviewer=viewer+viewerfacing*6;
+ check=0;
+
+ lightcolor[0]=light.color[0]*.5+light.ambient[0];
+ lightcolor[1]=light.color[1]*.5+light.ambient[1];
+ lightcolor[2]=light.color[2]*.5+light.ambient[2];
+
+ checkdelay-=multiplier*10;
+
+ if(checkdelay<=0){
+ check=1;
+ checkdelay=1;
+ }
+
+ lasttype=-1;
+ lastspecial=-1;
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+ blend = 1;
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(0);
+ glAlphaFunc(GL_GREATER, 0.0001);
+ for(i=0;i<numsprites;i++){
+ if(type[i]==cloudsprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, cloudtexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==cloudimpactsprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==breathsprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==smoketype&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, smoketexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==bloodsprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, bloodtexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==splintersprite&&(lasttype!=type[i]||lastspecial!=special[i])){
+ if(special[i]==0)glBindTexture( GL_TEXTURE_2D, splintertexture);
+ if(special[i]==1)glBindTexture( GL_TEXTURE_2D, leaftexture);
+ if(special[i]==2)glBindTexture( GL_TEXTURE_2D, snowflaketexture);
+ if(special[i]==3)glBindTexture( GL_TEXTURE_2D, toothtexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==snowsprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, snowflaketexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]==weaponshinesprite&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, shinetexture);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ }
+ }
+ if((type[i]==flamesprite||type[i]==weaponflamesprite)&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, flametexture);
+ if(blend||lasttype==bloodflamesprite){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.3);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+ }
+ }
+ if((type[i]==bloodflamesprite)&&lasttype!=type[i]){
+ glBindTexture( GL_TEXTURE_2D, bloodflametexture);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.3);
+ glBlendFunc(GL_ONE,GL_ZERO);
+ //glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(type[i]!=snowsprite)distancemult=(viewdistsquared-(findDistancefast(&viewer,&position[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ if(type[i]==snowsprite)distancemult=(144-(findDistancefast(&tempviewer,&position[i])-(144*fadestart))*(1/(1-fadestart)))/144;
+ if(type[i]!=flamesprite){
+ if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]);
+ if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*distancemult);
+ }
+ if(type[i]==flamesprite){
+ if(distancemult>=1)glColor4f(color[i][0],color[i][1],color[i][2],opacity[i]);
+ if(distancemult<1)glColor4f(color[i][0],color[i][1],color[i][2],opacity[i]*distancemult);
+ }
+ lasttype=type[i];
+ lastspecial=special[i];
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glTranslatef(position[i].x,position[i].y,position[i].z);
+ if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite)){
+ difference=viewer-position[i];
+ Normalise(&difference);
+ glTranslatef(difference.x*size[i]/4, difference.y*size[i]/4, difference.z*size[i]/4);
+ }
+ if(type[i]==snowsprite){
+ glRotatef(rotation[i]*.2,0,.3,1);
+ glTranslatef(1,0,0);
+ }
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ point.x=M[12];
+ point.y=M[13];
+ point.z=M[14];
+ glLoadIdentity();
+ glTranslatef(point.x, point.y, point.z);
+
+ glRotatef(rotation[i],0,0,1);
+
+ if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite)){
+ if(alivetime[i]<.14)glScalef(alivetime[i]/.14,alivetime[i]/.14,alivetime[i]/.14);
+ }
+ if(type[i]==smoketype||type[i]==snowsprite||type[i]==weaponshinesprite||type[i]==breathsprite){
+ if(alivetime[i]<.3){
+ if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*alivetime[i]/.3);
+ if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*distancemult*alivetime[i]/.3);
+ }
+ }
+ if(type[i]==splintersprite&&special[i]>0&&special[i]!=3){
+ if(alivetime[i]<.2){
+ if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],alivetime[i]/.2);
+ if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],distancemult*alivetime[i]/.2);
+ }
+ else{
+ if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
+ if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
+ }
+ }
+ if(type[i]==splintersprite&&(special[i]==0||special[i]==3)){
+ if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
+ if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
+ }
+ /*
+ if(type[i]==snowsprite){
+ glRotatef(rotation[i],0,0,1);
+ glTranslatef(1,0,0);
+ }*/
+
+ glBegin(GL_TRIANGLES);
+ glTexCoord2f(1.0f, 1.0f); glVertex3f( .5*size[i], .5*size[i], 0.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*size[i], .5*size[i], 0.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*size[i],-.5*size[i], 0.0f);
+ glTexCoord2f(0.0f, 0.0f); glVertex3f(-.5*size[i],-.5*size[i], 0.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*size[i], -.5*size[i], 0.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*size[i], .5*size[i], 0.0f);
+ glEnd();
+ glPopMatrix();
+ }
+ tempmult=multiplier;
+ for(i=numsprites-1;i>=0;i--){
+ multiplier=tempmult;
+ if(type[i]!=snowsprite)position[i]+=velocity[i]*multiplier;
+ if(type[i]!=snowsprite)velocity[i]+=windvector*multiplier;
+ if(type[i]==flamesprite||type[i]==smoketype)position[i]+=windvector*multiplier/2;
+ if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite))multiplier*=speed[i]*.7;
+ alivetime[i]+=multiplier;
+
+ if(type[i]==cloudsprite||type[i]==cloudimpactsprite){
+ opacity[i]-=multiplier/2;
+ size[i]+=multiplier/2;
+ velocity[i].y+=gravity*multiplier*.25;
+ }
+ if(type[i]==breathsprite){
+ opacity[i]-=multiplier/2;
+ size[i]+=multiplier/2;
+ if(findLength(&velocity[i])<=multiplier)velocity[i]=0;
+ else{
+ XYZ slowdown;
+ slowdown=velocity[i]*-1;
+ Normalise(&slowdown);
+ slowdown*=multiplier;
+ velocity[i]+=slowdown;
+ }
+ }
+ if(type[i]==snowsprite){
+ size[i]-=multiplier/120;
+ rotation[i]+=multiplier*360;
+ position[i].y-=multiplier;
+ position[i]+=windvector*multiplier;
+ if(position[i].y<tempviewer.y-6)position[i].y+=12;
+ if(position[i].y>tempviewer.y+6)position[i].y-=12;
+ if(position[i].z<tempviewer.z-6)position[i].z+=12;
+ if(position[i].z>tempviewer.z+6)position[i].z-=12;
+ if(position[i].x<tempviewer.x-6)position[i].x+=12;
+ if(position[i].x>tempviewer.x+6)position[i].x-=12;
+ }
+ if(type[i]==bloodsprite){
+ bool spritehit=0;
+ rotation[i]+=multiplier*100;
+ velocity[i].y+=gravity*multiplier;
+ if(check){
+ XYZ where,startpoint,endpoint,movepoint,footpoint;
+ float rotationpoint;
+ int whichtri;
+
+ for(j=0;j<numplayers;j++){
+ if(!spritehit&&player[j].dead&&alivetime[i]>.1){
+ where=oldposition[i];
+ where-=player[j].coords;
+ if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
+ startpoint=where;
+ where=position[i];
+ where-=player[j].coords;
+ if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
+ endpoint=where;
+
+ movepoint=0;
+ rotationpoint=0;
+ whichtri=player[j].skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
+ if(whichtri!=-1){
+ spritehit=1;
+ player[j].DoBloodBigWhere(0,160,oldposition[i]);
+ DeleteSprite(i);
+ }
+ }
+ }
+
+ whichpatchx=position[i].x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=position[i].z/(terrain.size/subdivision*terrain.scale*terraindetail);
+ if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
+ if(!spritehit)
+ for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][j];
+ start=oldposition[i];
+ end=position[i];
+ if(!spritehit)
+ if(objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k])!=-1){
+ if(detail==2||(detail==1&&abs(Random()%4)==0)||(detail==0&&abs(Random()%8)==0))objects.model[k].MakeDecal(blooddecalfast,DoRotation(colpoint-objects.position[k],0,-objects.rotation[k],0),size[i]*1.6/*+abs((float)(Random()%100))/2400*/,.5,Random()%360);
+ DeleteSprite(i);
+ spritehit=1;
+ }
+ }
+ }
+ if(!spritehit)
+ if(position[i].y<terrain.getHeight(position[i].x,position[i].z)){
+ terrain.MakeDecal(blooddecalfast,position[i],size[i]*1.6/*+abs((float)(Random()%100))/2400*/,.6,Random()%360);
+ DeleteSprite(i);
+ }
+ }
+ }
+ if(type[i]==splintersprite){
+ rotation[i]+=rotatespeed[i]*multiplier;
+ opacity[i]-=multiplier/2;
+ if(special[i]==0||special[i]==2||special[i]==3)velocity[i].y+=gravity*multiplier;
+ if(special[i]==1)velocity[i].y+=gravity*multiplier*.5;
+ }
+ if(type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite){
+ rotation[i]+=multiplier*rotatespeed[i];
+ opacity[i]-=multiplier*5/4;
+ if(type[i]!=weaponshinesprite&&type[i]!=bloodflamesprite)
+ if(opacity[i]<.5&&opacity[i]+multiplier*5/4>=.5&&(abs(Random()%4)==0||(initialsize[i]>2&&Random()%2==0)))MakeSprite(smoketype, position[i],velocity[i], .9,.9,.6, size[i]*1.2, .4);
+ if(alivetime[i]>.14&&(type[i]==flamesprite)){
+ velocity[i]=0;
+ velocity[i].y=1.5;
+ }
+ }
+ /*if(type[i]==smoketype){
+ opacity[i]-=multiplier/3/initialsize[i];
+ size[i]+=multiplier;
+ velocity[i]=0;
+ velocity[i].y=1.5;
+ rotation[i]+=multiplier*rotatespeed[i]/5;
+ }*/
+ if(type[i]==smoketype){
+ opacity[i]-=multiplier/3/initialsize[i];
+ color[i][0]-=multiplier;
+ color[i][1]-=multiplier;
+ color[i][2]-=multiplier;
+ if(color[i][0]<.6)color[i][0]=.6;
+ if(color[i][1]<.6)color[i][1]=.6;
+ if(color[i][2]<.6)color[i][2]=.6;
+ size[i]+=multiplier;
+ velocity[i]=0;
+ velocity[i].y=1.5;
+ rotation[i]+=multiplier*rotatespeed[i]/5;
+ }
+ if(opacity[i]<=0||size[i]<=0)DeleteSprite(i);
+ }
+ if(check)
+ for(i=numsprites-1;i>=0;i--){
+ oldposition[i]=position[i];
+ }
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void Sprites::DeleteSprite(int which)
+{
+ type[which]=type[numsprites-1];
+ rotation[which]=rotation[numsprites-1];
+ alivetime[which]=alivetime[numsprites-1];
+ opacity[which]=opacity[numsprites-1];
+ position[which]=position[numsprites-1];
+ velocity[which]=velocity[numsprites-1];
+ size[which]=size[numsprites-1];
+ speed[which]=speed[numsprites-1];
+ special[which]=special[numsprites-1];
+ color[which][0]=color[numsprites-1][0];
+ color[which][1]=color[numsprites-1][1];
+ color[which][2]=color[numsprites-1][2];
+ numsprites--;
+}
+
+void Sprites::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity){
+ if(numsprites<max_sprites-1){
+ if((atype!=bloodsprite&&atype!=bloodflamesprite)||bloodtoggle){
+ special[numsprites]=0;
+ type[numsprites]=atype;
+ position[numsprites]=where;
+ oldposition[numsprites]=where;
+ velocity[numsprites]=avelocity;
+ alivetime[numsprites]=0;
+ opacity[numsprites]=aopacity;
+ size[numsprites]=asize;
+ initialsize[numsprites]=asize;
+ color[numsprites][0]=red;
+ color[numsprites][1]=green;
+ color[numsprites][2]=blue;
+ rotatespeed[numsprites]=abs(Random()%720)-360;
+ speed[numsprites]=float(abs(Random()%100))/200+1.5;
+ }
+ numsprites++;
+ }
+}
+
+Sprites::Sprites()
+{
+ cloudtexture = 0;
+ cloudimpacttexture = 0;
+ bloodtexture = 0;
+ flametexture = 0;
+ bloodflametexture = 0;
+ smoketexture = 0;
+ snowflaketexture = 0;
+ shinetexture = 0;
+ splintertexture = 0;
+ leaftexture = 0;
+ toothtexture = 0;
+
+ memset(oldposition, 0, sizeof(oldposition));
+ memset(position, 0, sizeof(position));
+ memset(velocity, 0, sizeof(velocity));
+ memset(size, 0, sizeof(size));
+ memset(initialsize, 0, sizeof(initialsize));
+ memset(type, 0, sizeof(type));
+ memset(special, 0, sizeof(special));
+ memset(color, 0, sizeof(color));
+ memset(opacity, 0, sizeof(opacity));
+ memset(rotation, 0, sizeof(rotation));
+ memset(alivetime, 0, sizeof(alivetime));
+ memset(speed, 0, sizeof(speed));
+ memset(rotatespeed, 0, sizeof(rotatespeed));
+
+ checkdelay = 0;
+ numsprites = 0;
+}
+Sprites::~Sprites()
+{
+ if (toothtexture) glDeleteTextures( 1, (const unsigned long *)&toothtexture );
+ if (cloudtexture) glDeleteTextures( 1, (const unsigned long *)&cloudtexture );
+ if (cloudimpacttexture) glDeleteTextures( 1, (const unsigned long *)&cloudimpacttexture );
+ if (bloodtexture) glDeleteTextures( 1, (const unsigned long *)&bloodtexture );
+ if (flametexture) glDeleteTextures( 1, (const unsigned long *)&flametexture );
+ if (bloodflametexture) glDeleteTextures( 1, (const unsigned long *)&bloodflametexture );
+ if (smoketexture) glDeleteTextures( 1, (const unsigned long *)&smoketexture );
+ if (snowflaketexture) glDeleteTextures( 1, (const unsigned long *)&snowflaketexture );
+ if (shinetexture) glDeleteTextures( 1, (const unsigned long *)&shinetexture );
+ if (splintertexture) glDeleteTextures( 1, (const unsigned long *)&splintertexture );
+ if (leaftexture) glDeleteTextures( 1, (const unsigned long *)&leaftexture );
+}
--- /dev/null
+#ifndef _SPRITES_H_
+#define _SPRITES_H_
+
+#include "Quaternions.h"
+#include "gl.h"
+#include "TGALoader.h"
+#include "Quaternions.h"
+#include "Frustum.h"
+#include "Lights.h"
+#include "Terrain.h"
+#include "Objects.h"
+//
+// Model Structures
+//
+
+#define max_sprites 20000
+
+#define cloudsprite 0
+#define bloodsprite 1
+#define flamesprite 2
+#define smoketype 3
+#define weaponflamesprite 4
+#define cloudimpactsprite 5
+#define snowsprite 6
+#define weaponshinesprite 7
+#define bloodflamesprite 8
+#define breathsprite 9
+#define splintersprite 10
+
+class Sprites{
+public:
+ GLuint cloudtexture;
+ GLuint cloudimpacttexture;
+ GLuint bloodtexture;
+ GLuint flametexture;
+ GLuint bloodflametexture;
+ GLuint smoketexture;
+ GLuint snowflaketexture;
+ GLuint shinetexture;
+ GLuint splintertexture;
+ GLuint leaftexture;
+ GLuint toothtexture;
+
+ XYZ oldposition[max_sprites];
+ XYZ position[max_sprites];
+ XYZ velocity[max_sprites];
+ float size[max_sprites];
+ float initialsize[max_sprites];
+ int type[max_sprites];
+ int special[max_sprites];
+ float color[max_sprites][3];
+ float opacity[max_sprites];
+ float rotation[max_sprites];
+ float alivetime[max_sprites];
+ float speed[max_sprites];
+ float rotatespeed[max_sprites];
+ float checkdelay;
+ int numsprites;
+
+ void DeleteSprite(int which);
+ void MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity);
+ void Draw();
+
+ Sprites();
+ ~Sprites();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "TGALoader.h"
+#include "Game.h"
+
+extern float texdetail;
+extern TGAImageRec texture;
+extern short vRefNum;
+extern long dirID;
+extern bool visibleloading;
+extern Game * pgame;
+extern int loadscreencolor;
+
+extern bool LoadImage(const char * fname, TGAImageRec & tex);
+/********************> LoadTGA() <*****/
+bool upload_image(const unsigned char* filePath, bool hasalpha)
+{
+ if(visibleloading){
+ loadscreencolor=1;
+ pgame->LoadingScreen();
+ }
+
+#ifdef WIN32
+
+ // for Windows, just use TGA loader for now
+ char fileName[ 256];
+ CopyPascalStringToC( filePath, fileName);
+/*
+ // change extension to .TGA
+ int len = strlen( fileName);
+ if (len > 3)
+ {
+ fileName[ len - 3] = 't';
+ fileName[ len - 2] = 'g';
+ fileName[ len - 1] = 'a';
+ }
+*/
+// return (LoadTGA( fileName) != NULL);
+ return (LoadImage(fileName, texture));
+
+#else
+
+ OSStatus err;
+ ComponentResult cr;
+
+ /*FSRef fsref;
+ Boolean isdir;
+ err = FSPathMakeRef((const UInt8*)filePath, &fsref, &isdir);
+ if(err)return;
+
+ FSSpec fsspec;
+ err = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL);
+ if(err)return;
+ */
+
+ //Boolean isdir;
+ FSSpec fsspec;
+ //err = FSMakeFSSpec (0, 0, (const unsigned char*)filePath, &fsspec);
+ err = FSMakeFSSpec (0, 0, filePath, &fsspec);
+ //err=FSPathMakeFSSpec((const UInt8*)filePath,&fsspec,&isdir);*/
+ if(err)return;
+
+ GraphicsImportComponent gi;
+ err = GetGraphicsImporterForFile(&fsspec, &gi);
+ if(err)return;
+
+ Rect natbounds;
+ cr = GraphicsImportGetNaturalBounds(gi, &natbounds);
+
+ size_t buffersize = 4 * natbounds.bottom * natbounds.right;
+ //void* buf = malloc(buffersize);
+ texture.sizeX=natbounds.right;
+ texture.sizeY=natbounds.bottom;
+ /*if(hasalpha)*/texture.bpp = 32;
+ //if(!hasalpha)texture.bpp = 24;
+
+ GWorldPtr gw;
+ err = QTNewGWorldFromPtr(&gw, k32ARGBPixelFormat, &natbounds, NULL, NULL,
+ 0, texture.data, 4 * natbounds.right);
+ if(err)return;
+
+ cr = GraphicsImportSetGWorld(gi, gw, NULL);
+
+ natbounds.top = natbounds.bottom;
+ natbounds.bottom = 0;
+
+ cr = GraphicsImportSetBoundsRect(gi, &natbounds);
+
+ cr = GraphicsImportDraw(gi);
+
+ err = CloseComponent(gi);
+ if(err)return;
+
+ /*glTexImage2D(textureTarget, 0, GL_RGBA, natbounds.right, natbounds.top, 0,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buf);
+ */
+
+ //free(buf);
+ DisposeGWorld(gw);
+
+ // Loop Through The Image Data
+ GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram
+ GLuint temp; // Temporary Variable
+ GLuint bytesPerPixel; // Temporary Variable
+ bytesPerPixel=texture.bpp/8;
+ imageSize = texture.sizeX * texture.sizeY * bytesPerPixel;
+ int alltrans=10;
+
+ for( GLuint i = 0; i < int( imageSize ); i += 4 )
+ {
+ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
+ temp = texture.data[i]; // Temporarily Store The Value At Image Data 'i'
+ texture.data[i] = texture.data[i + 1]; // Set The 1st Byte To The Value Of The 3rd Byte
+ texture.data[i + 1] = texture.data[i + 2]; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
+ texture.data[i + 2] = texture.data[i + 3];
+ texture.data[i + 3] = temp;
+ }
+
+ int tempplace;
+ tempplace=0;
+ if(!hasalpha){
+ for( GLuint i = 0; i < int( imageSize ); i += 4 )
+ {
+ texture.data[i + 3] = 255;
+ /*texture.data[tempplace] = texture.data[i]; // Set The 1st Byte To The Value Of The 3rd Byte
+ texture.data[tempplace + 1] = texture.data[i + 1]; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
+ texture.data[tempplace + 2] = texture.data[i + 2];
+ tempplace+=3;*/
+ }
+ }
+
+ if(texdetail>1){
+ int which=0;
+ float temp;
+ float howmany;
+ for( GLuint k = 0; k < int( imageSize); k += bytesPerPixel*texture.sizeX*texdetail )
+ {
+ for( GLuint i = 0; i < int( imageSize/texture.sizeY ); i += bytesPerPixel*texdetail )
+ {
+ for( GLuint b = 0; b < bytesPerPixel ; b ++ ){
+ temp=0;
+ howmany=0;
+ for( GLuint l = 0; l < texdetail*texture.sizeX ; l +=texture.sizeX ){
+ for( GLuint j = 0; j < texdetail ; j ++ )
+ {
+ temp += (int)texture.data[k+i+j*bytesPerPixel+l*bytesPerPixel+b]; // Set The 1st Byte To The Value Of The 3rd Byte
+ howmany++;
+ }
+ }
+ texture.data[which+b]=GLubyte(temp/howmany);
+ }
+ which+=bytesPerPixel;
+ }
+ }
+ texture.sizeX/=texdetail;
+ texture.sizeY/=texdetail;
+ }
+
+ return true;
+
+#endif
+}
+
+
+TGAImageRec* LoadTGA( char *filename )
+{
+ GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
+ GLubyte TGAcompare[12]; // Used To Compare TGA Header
+ GLubyte header[6]; // First 6 Useful Bytes From The Header
+ GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File
+ GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram
+ GLuint temp; // Temporary Variable
+ GLuint type = GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP)
+ //TGAImageRec *texture;
+ FILE *file;
+
+ // Open The TGA File
+ file = fopen( filename, "rb" );
+
+ if( ( file == NULL ) || // Does File Even Exist?
+ ( fread( TGAcompare, 1, sizeof( TGAcompare ), file ) != sizeof( TGAcompare ) ) || // Are There 12 Bytes To Read?
+ ( memcmp( TGAheader, TGAcompare, sizeof( TGAheader ) ) != 0 ) || // Does The Header Match What We Want?
+ ( fread( header, 1, sizeof( header ), file ) != sizeof( header ) ) )// If So Read Next 6 Header Bytes
+ {
+ // If anything failed then close the file and return false
+ if (file) fclose( file );
+ return NULL;
+ }
+
+ // Create a new RGBAImageRec
+ //texture = ( TGAImageRec* )malloc( sizeof( TGAImageRec ) );
+
+ // Determine the TGA width (highbyte*256+lowbyte) and height (highbyte*256+lowbyte)
+ texture.sizeX = (header[1] * 256 + header[0]);
+ texture.sizeY = (header[3] * 256 + header[2]);
+
+ // Make sure the height, width, and bit depth are valid
+ if( ( texture.sizeX <= 0 ) || ( texture.sizeY <= 0 ) || ( ( header[4] != 24 ) && ( header[4] != 32 ) ) )
+ {
+ // If anything failed then close the file, free up memory for the image, and return NULL
+ fclose( file );
+ //free( texture );
+ return NULL;
+ }
+
+ // Grab The TGA's Bits Per Pixel (24 or 32)
+ texture.bpp = header[4];
+ bytesPerPixel = texture.bpp/8; // Divide By 8 To Get The Bytes Per Pixel
+
+ // Calculate The Memory Required For The TGA Data
+ imageSize = texture.sizeX * texture.sizeY * bytesPerPixel;
+
+ // Reserve Memory To Hold The TGA Data
+ //texture.data = ( GLubyte* )malloc( imageSize );
+
+ // Make sure the right amount of memory was allocated
+ if( ( texture.data == NULL ) || ( fread( texture.data, 1, imageSize, file ) != imageSize ) )
+ {
+ // Free up the image data if there was any
+ // if( texture.data != NULL )
+ // free( texture.data );
+
+ // If anything failed then close the file, free up memory for the image, and return NULL
+ fclose( file );
+ // free( texture );
+ return NULL;
+ }
+
+ // Loop Through The Image Data
+ for( GLuint i = 0; i < int( imageSize ); i += bytesPerPixel )
+ {
+ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
+ temp = texture.data[i]; // Temporarily Store The Value At Image Data 'i'
+ texture.data[i] = texture.data[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
+ texture.data[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
+ }
+
+ if(texdetail>1){
+ int which=0;
+ float temp;
+ float howmany;
+ for( GLuint k = 0; k < int( imageSize); k += bytesPerPixel*texture.sizeX*texdetail )
+ {
+ for( GLuint i = 0; i < int( imageSize/texture.sizeY ); i += bytesPerPixel*texdetail )
+ {
+ for( GLuint b = 0; b < bytesPerPixel ; b ++ ){
+ temp=0;
+ howmany=0;
+ for( GLuint l = 0; l < texdetail*texture.sizeX ; l +=texture.sizeX ){
+ for( GLuint j = 0; j < texdetail ; j ++ )
+ {
+ temp += (int)texture.data[k+i+j*bytesPerPixel+l*bytesPerPixel+b]; // Set The 1st Byte To The Value Of The 3rd Byte
+ howmany++;
+ }
+ }
+ texture.data[which+b]=GLubyte(temp/howmany);
+ }
+ which+=bytesPerPixel;
+ }
+ }
+ texture.sizeX/=texdetail;
+ texture.sizeY/=texdetail;
+ }
+
+ // Close The File
+ fclose( file );
+ return &texture;
+}
\ No newline at end of file
--- /dev/null
+#pragma once
+
+#ifndef _TGA_LOADER_H_
+#define _TGA_LOADER_H_
+
+
+/**> HEADER FILES <**/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#define Polygon WinPolygon
+#include <windows.h>
+#undef Polygon
+#include <gl/gl.h>
+#else
+#include "gl.h"
+// #include "MoreFilesX.h"
+#endif
+
+//#include <stdbool.h>
+//#include <QuickTime.h>
+
+/**> DATA STRUCTURES <**/
+typedef struct TGAImageRec
+{
+ GLubyte *data; // Image Data (Up To 32 Bits)
+ GLuint bpp; // Image Color Depth In Bits Per Pixel.
+ GLuint sizeX;
+ GLuint sizeY;
+} TGAImageRec;
+
+bool upload_image(const unsigned char* filePath, bool hasalpha);
+
+/**> FUNCTION PROTOTYPES <**/
+TGAImageRec* LoadTGA( char *filename );
+
+
+#endif
--- /dev/null
+#include "Terrain.h"
+#include "Objects.h"
+#include "Game.h"
+extern XYZ viewer;
+extern float viewdistance;
+extern float lightambient[3],lightbrightness[3];
+extern float fadestart;
+extern int environment;
+extern float texscale;
+extern Light light;
+extern float multiplier;
+extern FRUSTUM frustum;
+extern float texdetail,terraindetail;
+extern int detail;
+extern bool decals;
+extern float blurness;
+extern float targetblurness;
+extern Objects objects;
+extern TGAImageRec texture;
+extern Game * pgame;
+extern bool visibleloading;
+extern bool skyboxtexture;
+extern int tutoriallevel;
+
+//Functions
+
+int Terrain::lineTerrain(XYZ p1,XYZ p2, XYZ *p)
+{
+ static int i,j,k;
+ static float distance;
+ static float olddistance;
+ static int intersecting;
+ static int firstintersecting;
+ static XYZ point;
+ static int startx,starty;
+ static float slope;
+ static int endx,endy;
+ static int numtris=(size-1)*(size-1)*2;
+ static float highest,lowest;
+
+ firstintersecting=-1;
+ olddistance=10000;
+ distance=1;
+
+ XYZ triangles[3];
+
+ p1/=scale;
+ p2/=scale;
+
+ startx=p1.x;
+ starty=p1.z;
+ endx=p2.x;
+ endy=p2.z;
+
+ if(startx>endx){i=endx;endx=startx;startx=i;}
+ if(starty>endy){i=endy;endy=starty;starty=i;}
+
+ if(startx<0)startx=0;
+ if(starty<0)starty=0;
+ if(endx>size-1)endx=size-1;
+ if(endy>size-1)endy=size-1;
+
+ for(i=startx;i<=endx;i++){
+ for(j=starty;j<=endy;j++){
+ highest=-1000;
+ lowest=1000;
+ for(k=0;k<2;k++){
+ if(heightmap[i+k][j]>highest)highest=heightmap[i+k][j];
+ if(heightmap[i+k][j]<lowest)lowest=heightmap[i+k][j];
+ if(heightmap[i+k][j+1]>highest)highest=heightmap[i+k][j+1];
+ if(heightmap[i+k][j+1]<lowest)lowest=heightmap[i+k][j+1];
+ }
+ if((p1.y<=highest||p2.y<=highest)&&(p1.y>=lowest||p2.y>=lowest)){
+ triangles[0].x=i;
+ triangles[0].y=heightmap[i][j];
+ triangles[0].z=j;
+
+ triangles[1].x=i;
+ triangles[1].y=heightmap[i][j+1];
+ triangles[1].z=j+1;
+
+ triangles[2].x=i+1;
+ triangles[2].y=heightmap[i+1][j];
+ triangles[2].z=j;
+
+ intersecting=LineFacet(p1,p2,triangles[0],triangles[1],triangles[2],&point);
+ distance=findDistancefast(&p1,&point);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting==1){olddistance=distance; firstintersecting=1; *p=point;}
+
+ triangles[0].x=i+1;
+ triangles[0].y=heightmap[i+1][j];
+ triangles[0].z=j;
+
+ triangles[1].x=i;
+ triangles[1].y=heightmap[i][j+1];
+ triangles[1].z=j+1;
+
+ triangles[2].x=i+1;
+ triangles[2].y=heightmap[i+1][j+1];
+ triangles[2].z=j+1;
+
+ intersecting=LineFacet(p1,p2,triangles[0],triangles[1],triangles[2],&point);
+ distance=findDistancefast(&p1,&point);
+ if((distance<olddistance||firstintersecting==-1)&&intersecting==1){olddistance=distance; firstintersecting=1; *p=point;}
+ }
+ }
+ }
+ return firstintersecting;
+}
+
+void Terrain::UpdateTransparency(int whichx, int whichy){
+ static XYZ vertex;
+ static int i,j,a,b,c,d,patch_size,stepsize;
+ static float distance;
+
+ static float viewdistsquared;
+
+ viewdistsquared=viewdistance*viewdistance;
+ patch_size=size/subdivision;
+
+ stepsize=1;
+ c=whichx*patch_elements+whichy*patch_elements*subdivision;
+
+ for(i=patch_size*whichx;i<patch_size*(whichx+1)+1;i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1)+1;j+=stepsize){
+ if(i<size&&j<size){
+ vertex.x=i*scale;
+ vertex.z=j*scale;
+ vertex.y=heightmap[i][j]*scale;
+ distance=findDistancefast(&viewer,&vertex);
+ if(distance>viewdistsquared)distance=viewdistsquared;
+ colors[i][j][3]=(viewdistsquared-(distance-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ }
+ }
+ }
+
+ for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
+ a=(i-(patch_size*whichx))/stepsize;
+ b=(j-(patch_size*whichy))/stepsize;
+ d=(a*54)+(b*54*patch_size/stepsize);
+ vArray[d+c+6]=colors[i][j][3];
+
+ vArray[d+c+15]=colors[i][j+stepsize][3];
+
+ vArray[d+c+24]=colors[i+stepsize][j][3];
+
+ vArray[d+c+33]=colors[i+stepsize][j][3];
+
+ vArray[d+c+42]=colors[i][j+stepsize][3];
+
+ vArray[d+c+51]=colors[i+stepsize][j+stepsize][3];
+ }
+ }
+}
+
+void Terrain::UpdateTransparencyother(int whichx, int whichy){
+ static XYZ vertex;
+ static int i,j,a,b,c,d,patch_size,stepsize;
+ static float distance;
+
+ patch_size=size/subdivision;
+
+ stepsize=1;
+ c=whichx*patch_elements+whichy*patch_elements*subdivision;
+
+ for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
+ a=(i-(patch_size*whichx))/stepsize;
+ b=(j-(patch_size*whichy))/stepsize;
+ d=(a*54)+(b*54*patch_size/stepsize);
+ vArray[d+c+6]=colors[i][j][3]*opacityother[i][j];
+
+ vArray[d+c+15]=colors[i][j+stepsize][3]*opacityother[i][j+stepsize];
+
+ vArray[d+c+24]=colors[i+stepsize][j][3]*opacityother[i+stepsize][j];
+
+ vArray[d+c+33]=colors[i+stepsize][j][3]*opacityother[i+stepsize][j];
+
+ vArray[d+c+42]=colors[i][j+stepsize][3]*opacityother[i][j+stepsize];
+
+ vArray[d+c+51]=colors[i+stepsize][j+stepsize][3]*opacityother[i+stepsize][j+stepsize];
+ }
+ }
+}
+
+void Terrain::UpdateTransparencyotherother(int whichx, int whichy){
+ static XYZ vertex;
+ static int i,j,a,b,c,d,patch_size,stepsize;
+ static float distance;
+
+ static float viewdistsquared;
+
+ viewdistsquared=viewdistance*viewdistance;
+ patch_size=size/subdivision;
+
+ stepsize=1;
+ c=whichx*patch_elements+whichy*patch_elements*subdivision;
+
+ for(i=patch_size*whichx;i<patch_size*(whichx+1)+1;i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1)+1;j+=stepsize){
+ if(i<size&&j<size){
+ vertex.x=i*scale;
+ vertex.z=j*scale;
+ vertex.y=heightmap[i][j]*scale;
+ distance=findDistancefast(&viewer,&vertex);
+ if(distance>viewdistsquared)distance=viewdistsquared;
+ colors[i][j][3]=(viewdistsquared-(distance-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ }
+ }
+ }
+
+ for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
+ a=(i-(patch_size*whichx))/stepsize;
+ b=(j-(patch_size*whichy))/stepsize;
+ d=(a*54)+(b*54*patch_size/stepsize);
+ vArray[d+c+6]=colors[i][j][3];
+
+ vArray[d+c+15]=colors[i][j+stepsize][3];
+
+ vArray[d+c+24]=colors[i+stepsize][j][3];
+
+ vArray[d+c+33]=colors[i+stepsize][j][3];
+
+ vArray[d+c+42]=colors[i][j+stepsize][3];
+
+ vArray[d+c+51]=colors[i+stepsize][j+stepsize][3];
+ }
+ }
+}
+
+void Terrain::UpdateVertexArray(int whichx, int whichy){
+ static int i,j,a,b,c,patch_size,stepsize;
+
+
+ numtris[whichx][whichy]=0;
+
+ patch_size=size/subdivision;
+
+ stepsize=1;
+ c=whichx*patch_elements+whichy*patch_elements*subdivision;
+ for(i=patch_size*whichx;i<patch_size*(whichx+1);i+=stepsize){
+ for(j=patch_size*whichy;j<patch_size*(whichy+1);j+=stepsize){
+ a=(i-((float)size/subdivision*(float)whichx))/stepsize;
+ b=(j-((float)size/subdivision*(float)whichy))/stepsize;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+0]=i*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+1]=heightmap[i][j]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+2]=j*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+3]=colors[i][j][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+4]=colors[i][j][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+5]=colors[i][j][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+6]=colors[i][j][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+7]=i*scale*texscale+texoffsetx[i][j];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+8]=j*scale*texscale+texoffsety[i][j];
+
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+9]=i*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+10]=heightmap[i][j+stepsize]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+11]=j*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+12]=colors[i][j+stepsize][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+13]=colors[i][j+stepsize][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+14]=colors[i][j+stepsize][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+15]=colors[i][j+stepsize][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+16]=i*scale*texscale+texoffsetx[i][j+stepsize];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+17]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i][j+stepsize];
+
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+18]=i*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+19]=heightmap[i+stepsize][j]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+20]=j*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+21]=colors[i+stepsize][j][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+22]=colors[i+stepsize][j][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+23]=colors[i+stepsize][j][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+24]=colors[i+stepsize][j][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+25]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+26]=j*scale*texscale+texoffsety[i+stepsize][j];
+
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+27]=i*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+28]=heightmap[i+stepsize][j]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+29]=j*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+30]=colors[i+stepsize][j][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+31]=colors[i+stepsize][j][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+32]=colors[i+stepsize][j][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+33]=colors[i+stepsize][j][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+34]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+35]=j*scale*texscale+texoffsety[i+stepsize][j];
+
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+36]=i*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+37]=heightmap[i][j+stepsize]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+38]=j*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+39]=colors[i][j+stepsize][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+40]=colors[i][j+stepsize][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+41]=colors[i][j+stepsize][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+42]=colors[i][j+stepsize][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+43]=i*scale*texscale+texoffsetx[i][j+stepsize];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+44]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i][j+stepsize];
+
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+45]=i*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+46]=heightmap[i+stepsize][j+stepsize]*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+47]=j*scale+stepsize*scale;
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+48]=colors[i+stepsize][j+stepsize][0];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+49]=colors[i+stepsize][j+stepsize][1];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+50]=colors[i+stepsize][j+stepsize][2];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+51]=colors[i+stepsize][j+stepsize][3];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+52]=i*scale*texscale+stepsize*scale*texscale+texoffsetx[i+stepsize][j+stepsize];
+ vArray[(a*54)+(b*54*patch_size/stepsize)+c+53]=j*scale*texscale+stepsize*scale*texscale+texoffsety[i+stepsize][j+stepsize];
+ numtris[whichx][whichy]+=2;
+ }
+ }
+
+ maxypatch[whichx][whichy]=-10000;
+ minypatch[whichx][whichy]=10000;
+ for(a=0;a<size/subdivision;a++){
+ for(b=0;b<size/subdivision;b++){
+ if(heightmap[(size/subdivision)*whichx+a][(size/subdivision)*whichy+b]*scale>maxypatch[whichx][whichy]) maxypatch[whichx][whichy]=heightmap[(size/subdivision)*whichx+a][(size/subdivision)*whichy+b]*scale;
+ if(heightmap[(size/subdivision)*whichx+a][(size/subdivision)*whichy+b]*scale<minypatch[whichx][whichy]) minypatch[whichx][whichy]=heightmap[(size/subdivision)*whichx+a][(size/subdivision)*whichy+b]*scale;
+ }
+ }
+ heightypatch[whichx][whichy]=(maxypatch[whichx][whichy]-minypatch[whichx][whichy]);
+ if(heightypatch[whichx][whichy]<size/subdivision*scale)heightypatch[whichx][whichy]=size/subdivision*scale;
+ avgypatch[whichx][whichy]=(minypatch[whichx][whichy]+maxypatch[whichx][whichy])/2;
+
+ for(i=whichx*size/subdivision;i<(whichx+1)*size/subdivision-1;i++){
+ for(j=whichy*size/subdivision;j<(whichy+1)*size/subdivision-1;j++){
+ triangles[(i*(size-1)*2)+(j*2)][0].x=i*scale;
+ triangles[(i*(size-1)*2)+(j*2)][0].y=heightmap[i][j]*scale;
+ triangles[(i*(size-1)*2)+(j*2)][0].z=j*scale;
+
+ triangles[(i*(size-1)*2)+(j*2)][1].x=i*scale;
+ triangles[(i*(size-1)*2)+(j*2)][1].y=heightmap[i][j+1]*scale;
+ triangles[(i*(size-1)*2)+(j*2)][1].z=j*scale+scale;
+
+ triangles[(i*(size-1)*2)+(j*2)][2].x=i*scale+1*scale;
+ triangles[(i*(size-1)*2)+(j*2)][2].y=heightmap[i+1][j]*scale;
+ triangles[(i*(size-1)*2)+(j*2)][2].z=j*scale;
+
+ triangles[(i*(size-1)*2)+(j*2)+1][0].x=i*scale+1*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][0].y=heightmap[i+1][j]*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][0].z=j*scale;
+
+ triangles[(i*(size-1)*2)+(j*2)+1][1].x=i*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][1].y=heightmap[i][j+1]*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][1].z=j*scale+1*scale;
+
+ triangles[(i*(size-1)*2)+(j*2)+1][2].x=i*scale+1*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][2].y=heightmap[i+1][j+1]*scale;
+ triangles[(i*(size-1)*2)+(j*2)+1][2].z=j*scale+1*scale;
+ }
+ }
+
+}
+
+
+bool Terrain::load(char *fileName)
+{
+ static long i,j;
+ static long x,y;
+ static float patch_size;
+
+ float temptexdetail=texdetail;
+ texdetail=terraindetail;
+ //LoadTGA( fileName );
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ upload_image( fileNamep ,0);
+
+ //Is it valid?
+ if(texture.bpp>24){
+ int bytesPerPixel=texture.bpp/8;
+
+ int tempnum=0;
+ for(i=0;i<(long)(texture.sizeY*texture.sizeX*bytesPerPixel);i++){
+ if((i+1)%4){
+ texture.data[tempnum]=texture.data[i];
+ tempnum++;
+ }
+ }
+ }
+ texture.bpp=24;
+ if(visibleloading)pgame->LoadingScreen();
+
+ texdetail=temptexdetail;
+
+ size=128;
+ if(1==1){
+ /*if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!terraintexture)glGenTextures( 1, &terraintexture );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, terraintexture);
+ //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+ */
+
+ size=texture.sizeX;
+
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ heightmap[size-1-i][j]=(float)((texture.data[(i+(j*size))*texture.bpp/8]))/5/terraindetail;
+ }
+ }
+
+ }
+ if(visibleloading)pgame->LoadingScreen();
+
+ float slopeness;
+
+ for(i=0;i<subdivision;i++){
+ for(j=0;j<subdivision;j++){
+ textureness[i][j]=-1;
+ }
+ }
+ if(visibleloading)pgame->LoadingScreen();
+
+
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ heightmap[i][j]*=.5;
+
+ texoffsetx[i][j]=(float)abs(Random()%100)/1200/scale*3;
+ texoffsety[i][j]=(float)abs(Random()%100)/1200/scale*3;
+
+ slopeness=0;
+ if(environment==snowyenvironment){
+ if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
+ opacityother[i][j]=slopeness*slopeness*2;
+ if(opacityother[i][j]>1)opacityother[i][j]=1;
+ opacityother[i][j]-=(float)abs(Random()%100)/300;
+ }
+ if(environment==desertenvironment){
+ if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
+ opacityother[i][j]=slopeness*slopeness*2;
+ if(opacityother[i][j]>1)opacityother[i][j]=1;
+ opacityother[i][j]-=(float)abs(Random()%100)/300;
+ }
+ if(environment==grassyenvironment){
+ if(i!=0&&heightmap[i][j]-heightmap[i-1][j]>slopeness){ slopeness=heightmap[i][j]-heightmap[i-1][j];}
+ if(j!=0&&heightmap[i][j]-heightmap[i][j-1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j-1];}
+ if(i<size-1&&heightmap[i][j]-heightmap[i+1][j]>slopeness){ slopeness=heightmap[i][j]-heightmap[i+1][j];}
+ if(j<size-1&&heightmap[i][j]-heightmap[i][j+1]>slopeness){ slopeness=heightmap[i][j]-heightmap[i][j+1];}
+ opacityother[i][j]=slopeness*slopeness*10;
+ if(opacityother[i][j]>1)opacityother[i][j]=1;
+ opacityother[i][j]-=(float)abs(Random()%100)/100;
+ }
+ }
+ }
+ if(visibleloading)pgame->LoadingScreen();
+
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ if(environment==snowyenvironment){
+ heightmap[i][j]-=opacityother[i][j];
+ }
+ if(environment==desertenvironment){
+ heightmap[i][j]-=opacityother[i][j];
+ }
+ }
+ }
+ if(visibleloading)pgame->LoadingScreen();
+
+ /*float total;
+ int todivide;
+ //Smooth opacityother
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ total=0;
+ todivide=0;
+ if(i!=0){ total+=opacityother[j][i-1]; todivide++;}
+ if(i!=size-1){ total+=opacityother[j][i+1]; todivide++;}
+ if(j!=0){ total+=opacityother[j-1][i]; todivide++;}
+ if(j!=size-1){ total+=opacityother[j+1][i]; todivide++;}
+ if(i!=0&&j!=0){ total+=opacityother[j-1][i-1]; todivide++;}
+ if(i!=size-1&&j!=0){ total+=opacityother[j-1][i+1]; todivide++;}
+ if(j!=size-1&&i!=size-1){ total+=opacityother[j+1][i+1]; todivide++;}
+ if(j!=size-1&&i!=0){ total+=opacityother[j+1][i-1]; todivide++;}
+ total+=opacityother[j][i]; todivide++;
+
+ opacityother[j][i]=total/(float)todivide;
+ }
+ }*/
+
+
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ if(opacityother[i][j]<.1)opacityother[i][j]=0;
+ if(textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==-1){
+ if(!opacityother[i][j])textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=allfirst;
+ if(opacityother[i][j]==1)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=allsecond;
+ }
+ if(opacityother[i][j]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+
+ x=i;
+ y=j;
+ if(i>0){
+ i--;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+
+ if(j>0){
+ j--;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j++;
+ }
+
+ if(j<size-1){
+ j++;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j--;
+ }
+ i++;
+ }
+
+ if(i<size-1){
+ i++;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+
+ if(j>0){
+ j--;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j++;
+ }
+
+ if(j<size-1){
+ j++;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j--;
+ }
+ i--;
+ }
+
+ if(j>0){
+ j--;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j++;
+ }
+
+ if(j<size-1){
+ j++;
+ if(opacityother[x][y]&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allfirst)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[x][y]!=1&&textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]==allsecond)textureness[(int)(i*subdivision/size)][(int)(j*subdivision/size)]=mixed;
+ if(opacityother[i][j]&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allfirst)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ if(opacityother[i][j]!=1&&textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]==allsecond)textureness[(int)(x*subdivision/size)][(int)(y*subdivision/size)]=mixed;
+ j--;
+
+ }
+ }
+ }
+ if(visibleloading)pgame->LoadingScreen();
+
+ patch_size=size/subdivision;
+ patch_elements=(patch_size)*(patch_size)*54;
+ CalculateNormals();
+ /*DoShadows();
+
+ for(i=0;i<subdivision;i++){
+ for(j=0;j<subdivision;j++){
+ UpdateVertexArray(i,j);
+ }
+ }*/
+
+ return 1;
+}
+
+void Terrain::CalculateNormals()
+{
+ static int i,j;
+ static XYZ facenormal;
+ static XYZ p,q,a,b,c;
+
+ for(i=0; i<size; i++){
+ for(j=0; j<size; j++){
+ normals[i][j].x=0;
+ normals[i][j].y=0;
+ normals[i][j].z=0;
+ }
+ }
+
+ for(i=0;i<size-1;i++){
+ for(j=0;j<size-1;j++){
+ a.x=i;
+ a.y=heightmap[i][j];
+ a.z=j;
+ b.x=i;
+ b.y=heightmap[i][j+1];
+ b.z=j+1;
+ c.x=i+1;
+ c.y=heightmap[i+1][j];
+ c.z=j;
+
+ p.x=b.x-a.x;
+ p.y=b.y-a.y;
+ p.z=b.z-a.z;
+ q.x=c.x-a.x;
+ q.y=c.y-a.y;
+ q.z=c.z-a.z;
+
+ CrossProduct(&p,&q,&facenormal);
+
+ facenormals[i][j]=facenormal;
+
+ normals[i][j]=normals[i][j]+facenormal;
+ normals[i][j+1]=normals[i][j+1]+facenormal;
+ normals[i+1][j]=normals[i+1][j]+facenormal;
+
+
+ a.x=i+1;
+ a.y=heightmap[i+1][j];
+ a.z=j;
+ b.x=i;
+ b.y=heightmap[i][j+1];
+ b.z=j+1;
+ c.x=i+1;
+ c.y=heightmap[i+1][j+1];
+ c.z=j+1;
+
+ p.x=b.x-a.x;
+ p.y=b.y-a.y;
+ p.z=b.z-a.z;
+ q.x=c.x-a.x;
+ q.y=c.y-a.y;
+ q.z=c.z-a.z;
+
+ CrossProduct(&p,&q,&facenormal);
+
+ normals[i+1][j+1]=normals[i+1][j+1]+facenormal;
+ normals[i][j+1]=normals[i][j+1]+facenormal;
+ normals[i+1][j]=normals[i+1][j]+facenormal;
+
+ Normalise(&facenormals[i][j]);
+ }
+ }
+
+ for(i=0; i<size; i++){
+ for(j=0; j<size; j++){
+ Normalise(&normals[i][j]);
+ normals[i][j]=normals[i][j];
+ }
+ }
+}
+
+void Terrain::drawpatch(int whichx, int whichy, float opacity){
+ if(opacity>=1)glDisable(GL_BLEND);
+ if(opacity<1){
+ glEnable(GL_BLEND);
+ UpdateTransparency(whichx,whichy);
+ }
+ glColor4f(1,1,1,1);
+ //Set up vertex array
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
+
+ //Draw
+ glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void Terrain::drawpatchother(int whichx, int whichy, float opacity){
+ glEnable(GL_BLEND);
+ if(opacity<1){
+ UpdateTransparency(whichx,whichy);
+ }
+ UpdateTransparencyother(whichx,whichy);
+ glColor4f(1,1,1,1);
+ //Set up vertex array
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
+
+ //Draw
+ glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void Terrain::drawpatchotherother(int whichx, int whichy, float opacity){
+ glEnable(GL_BLEND);
+ UpdateTransparencyotherother(whichx,whichy);
+
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glScalef(6, 6, 6);
+
+ glColor4f(1,1,1,1);
+
+ //Set up vertex array
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 9*sizeof(GLfloat),&vArray[0+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glColorPointer(4,GL_FLOAT, 9*sizeof(GLfloat),&vArray[3+whichx*patch_elements+whichy*patch_elements*subdivision]);
+ glTexCoordPointer(2, GL_FLOAT, 9*sizeof(GLfloat),&vArray[7+whichx*patch_elements+whichy*patch_elements*subdivision]);
+
+ //Draw
+ glDrawArrays(GL_TRIANGLES, 0, numtris[whichx][whichy]*3);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+}
+
+
+float Terrain::getHeight(float pointx, float pointz)
+{
+ static float height1,height2;
+ static int tilex,tiley;
+ static XYZ startpoint,endpoint,intersect,triangle[3],average;
+
+ pointx/=scale;
+ pointz/=scale;
+
+ if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
+
+ startpoint.x=pointx;
+ startpoint.y=-1000;
+ startpoint.z=pointz;
+
+ endpoint=startpoint;
+ endpoint.y=1000;
+
+ tilex=pointx;
+ tiley=pointz;
+
+ triangle[0].x=tilex;
+ triangle[0].z=tiley;
+ triangle[0].y=heightmap[tilex][tiley];
+
+ triangle[1].x=tilex+1;
+ triangle[1].z=tiley;
+ triangle[1].y=heightmap[tilex+1][tiley];
+
+ triangle[2].x=tilex;
+ triangle[2].z=tiley+1;
+ triangle[2].y=heightmap[tilex][tiley+1];
+
+ if(!LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect)){
+ triangle[0].x=tilex+1;
+ triangle[0].z=tiley;
+ triangle[0].y=heightmap[tilex+1][tiley];
+
+ triangle[1].x=tilex+1;
+ triangle[1].z=tiley+1;
+ triangle[1].y=heightmap[tilex+1][tiley+1];
+
+ triangle[2].x=tilex;
+ triangle[2].z=tiley+1;
+ triangle[2].y=heightmap[tilex][tiley+1];
+ LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect);
+ }
+ return intersect.y*scale+getOpacity(pointx*scale,pointz*scale)/8;
+
+ //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
+ //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
+
+ //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
+}
+
+float Terrain::getHeightExtrude(float pointx, float pointz,float point2x, float point2z)
+{
+ static float height1,height2;
+ static int tilex,tiley;
+ static XYZ startpoint,endpoint,intersect,triangle[3],average;
+
+ pointx/=scale;
+ pointz/=scale;
+ point2x/=scale;
+ point2z/=scale;
+
+ if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
+ if(point2x>=size-1||point2z>=size-1||point2x<=0||point2z<=0)return 0;
+
+ startpoint.x=point2x;
+ startpoint.y=-1000;
+ startpoint.z=point2z;
+
+ endpoint=startpoint;
+ endpoint.y=1000;
+
+ tilex=pointx;
+ tiley=pointz;
+
+ triangle[0].x=tilex;
+ triangle[0].z=tiley;
+ triangle[0].y=heightmap[tilex][tiley];
+
+ triangle[1].x=tilex+1;
+ triangle[1].z=tiley;
+ triangle[1].y=heightmap[tilex+1][tiley];
+
+ triangle[2].x=tilex;
+ triangle[2].z=tiley+1;
+ triangle[2].y=heightmap[tilex][tiley+1];
+
+ XYZ mid;
+
+ mid=(triangle[0]+triangle[1]+triangle[2])/2;
+
+ triangle[0]=mid+(triangle[0]-mid)*10;
+ triangle[1]=mid+(triangle[0]-mid)*10;
+ triangle[2]=mid+(triangle[0]-mid)*10;
+
+ /*
+ if(!LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect)){
+ triangle[0].x=tilex+1;
+ triangle[0].z=tiley;
+ triangle[0].y=heightmap[tilex+1][tiley];
+
+ triangle[1].x=tilex+1;
+ triangle[1].z=tiley+1;
+ triangle[1].y=heightmap[tilex+1][tiley+1];
+
+ triangle[2].x=tilex;
+ triangle[2].z=tiley+1;
+ triangle[2].y=heightmap[tilex][tiley+1];
+ LineFacetd(&startpoint,&endpoint,&triangle[0],&triangle[1],&triangle[2],&intersect);
+ }*/
+ return intersect.y*scale+getOpacity(pointx*scale,pointz*scale)/8;
+
+ //height1=heightmap[tilex][tiley]*(1-(pointx-tilex))+heightmap[tilex+1][tiley]*(pointx-tilex);
+ //height2=heightmap[tilex][tiley+1]*(1-(pointx-tilex))+heightmap[tilex+1][tiley+1]*(pointx-tilex);
+
+ //return height1*(1-(pointz-tiley))*scale+height2*(pointz-tiley)*scale;
+}
+
+
+float Terrain::getOpacity(float pointx, float pointz)
+{
+ static float height1,height2;
+ static int tilex,tiley;
+
+ pointx/=scale;
+ pointz/=scale;
+
+ if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return 0;
+
+ tilex=pointx;
+ tiley=pointz;
+
+ height1=opacityother[tilex][tiley]*(1-(pointx-tilex))+opacityother[tilex+1][tiley]*(pointx-tilex);
+ height2=opacityother[tilex][tiley+1]*(1-(pointx-tilex))+opacityother[tilex+1][tiley+1]*(pointx-tilex);
+
+ return height1*(1-(pointz-tiley))+height2*(pointz-tiley);
+}
+
+XYZ Terrain::getNormal(float pointx, float pointz)
+{
+ static XYZ height1,height2,total;
+ static int tilex,tiley;
+
+ pointx/=scale;
+ pointz/=scale;
+
+ height1=0;
+ if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return height1;
+ tilex=pointx;
+ tiley=pointz;
+
+ height1=normals[tilex][tiley]*(1-(pointx-tilex))+normals[tilex+1][tiley]*(pointx-tilex);
+ height2=normals[tilex][tiley+1]*(1-(pointx-tilex))+normals[tilex+1][tiley+1]*(pointx-tilex);
+ total=height1*(1-(pointz-tiley))+height2*(pointz-tiley);
+ Normalise(&total);
+ return total;
+}
+
+XYZ Terrain::getLighting(float pointx, float pointz)
+{
+ static XYZ height1,height2;
+ static int tilex,tiley;
+
+ pointx/=scale;
+ pointz/=scale;
+
+ height1=0;
+ if(pointx>=size-1||pointz>=size-1||pointx<=0||pointz<=0)return height1;
+ tilex=pointx;
+ tiley=pointz;
+
+ height1.x=colors[tilex][tiley][0]*(1-(pointx-tilex))+colors[tilex+1][tiley][0]*(pointx-tilex);
+ height1.y=colors[tilex][tiley][1]*(1-(pointx-tilex))+colors[tilex+1][tiley][1]*(pointx-tilex);
+ height1.z=colors[tilex][tiley][2]*(1-(pointx-tilex))+colors[tilex+1][tiley][2]*(pointx-tilex);
+ height2.x=colors[tilex][tiley+1][0]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][0]*(pointx-tilex);
+ height2.y=colors[tilex][tiley+1][1]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][1]*(pointx-tilex);
+ height2.z=colors[tilex][tiley+1][2]*(1-(pointx-tilex))+colors[tilex+1][tiley+1][2]*(pointx-tilex);
+
+ return height1*(1-(pointz-tiley))+height2*(pointz-tiley);
+}
+
+void Terrain::draw(int layer)
+{
+ static int i,j;
+ static float opacity;
+ static XYZ terrainpoint;
+ static float distance[subdivision][subdivision];
+
+ static int beginx,endx;
+ static int beginz,endz;
+
+ static float patch_size=size/subdivision*scale;
+ static float viewdistsquared;
+
+ viewdistsquared=viewdistance*viewdistance;
+
+ //Only nearby blocks
+ beginx=(viewer.x-viewdistance)/(patch_size)-1;
+ if(beginx<0)beginx=0;
+ beginz=(viewer.z-viewdistance)/(patch_size)-1;
+ if(beginz<0)beginz=0;
+
+ endx=(viewer.x+viewdistance)/(patch_size)+1;
+ if(endx>subdivision)endx=subdivision;
+ endz=(viewer.z+viewdistance)/(patch_size)+1;
+ if(endz>subdivision)endz=subdivision;
+
+ if(!layer)
+ for(i=beginx;i<endx;i++){
+ for(j=beginz;j<endz;j++){
+ terrainpoint.x=i*patch_size+(patch_size)/2;
+ terrainpoint.y=viewer.y;//heightmap[i][j]*scale;
+ terrainpoint.z=j*patch_size+(patch_size)/2;
+ distance[i][j]=findDistancefast(&viewer,&terrainpoint);
+ }
+ }
+
+ for(i=beginx;i<endx;i++){
+ for(j=beginz;j<endz;j++){
+ if(distance[i][j]<(viewdistance+patch_size)*(viewdistance+patch_size)){
+ opacity=1;
+ if(distance[i][j]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
+ if(opacity==1&&i!=subdivision)if(distance[i+1][j]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
+ if(opacity==1&&j!=subdivision)if(distance[i][j+1]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
+ if(opacity==1&&j!=subdivision&&i!=subdivision)if(distance[i+1][j+1]>viewdistsquared*fadestart-viewdistsquared)opacity=0;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ if(frustum.CubeInFrustum(i*patch_size+patch_size*.5,avgypatch[i][j],j*patch_size+patch_size*.5,heightypatch[i][j]/2))
+ {
+ if(environment==desertenvironment&&distance[i][j]>viewdistsquared/4)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, blurness);
+ else if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
+ if(!layer&&textureness[i][j]!=allsecond)drawpatch(i,j,opacity);
+ if(layer==1&&textureness[i][j]!=allfirst)drawpatchother(i,j,opacity);
+ if(layer==2&&textureness[i][j]!=allfirst)drawpatchotherother(i,j,opacity);
+ }
+ glPopMatrix();
+ }
+ }
+ }
+ if(environment==desertenvironment)glTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0 );
+}
+
+void Terrain::drawdecals()
+{
+ if(decals){
+ static int i,j;
+ static float distancemult;
+ static int lasttype;
+
+ static float patch_size=size/subdivision*scale;
+ static float viewdistsquared;
+ static bool blend;
+
+ viewdistsquared=viewdistance*viewdistance;
+ blend=1;
+
+ lasttype=-1;
+ glEnable(GL_BLEND);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_CULL_FACE);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDepthMask(0);
+ for(i=0;i<numdecals;i++){
+ if(decaltype[i]==blooddecalfast&&decalalivetime[i]<2)decalalivetime[i]=2;
+ if((decaltype[i]==shadowdecal||decaltype[i]==shadowdecalpermanent)&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, shadowtexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(decaltype[i]==footprintdecal&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, footprinttexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if(decaltype[i]==bodyprintdecal&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, bodyprinttexture);
+ if(!blend){
+ blend=1;
+ glAlphaFunc(GL_GREATER, 0.0001);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalslow)&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, bloodtexture);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.15);
+ glBlendFunc(GL_ONE,GL_ZERO);
+ }
+ }
+ if((decaltype[i]==blooddecalfast)&&decaltype[i]!=lasttype){
+ glBindTexture( GL_TEXTURE_2D, bloodtexture2);
+ if(blend){
+ blend=0;
+ glAlphaFunc(GL_GREATER, 0.15);
+ glBlendFunc(GL_ONE,GL_ZERO);
+ }
+ }
+ if(decaltype[i]==shadowdecal||decaltype[i]==shadowdecalpermanent){
+ distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ if(distancemult>=1)glColor4f(1,1,1,decalopacity[i]);
+ if(distancemult<1)glColor4f(1,1,1,decalopacity[i]*distancemult);
+ }
+ if(decaltype[i]==footprintdecal||decaltype[i]==bodyprintdecal){
+ distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ if(distancemult>=1){
+ glColor4f(1,1,1,decalopacity[i]);
+ if(decalalivetime[i]>3)glColor4f(1,1,1,decalopacity[i]*(5-decalalivetime[i])/2);
+ }
+ if(distancemult<1){
+ glColor4f(1,1,1,decalopacity[i]*distancemult);
+ if(decalalivetime[i]>3)glColor4f(1,1,1,decalopacity[i]*(5-decalalivetime[i])/2*distancemult);
+ }
+ }
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)){
+ distancemult=(viewdistsquared-(findDistancefast(&viewer,&decalposition[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
+ if(distancemult>=1){
+ glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]);
+ if(decalalivetime[i]<4)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*decalalivetime[i]*.25);
+ if(decalalivetime[i]>58)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*(60-decalalivetime[i])/2);
+ }
+ if(distancemult<1){
+ glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*distancemult);
+ if(decalalivetime[i]<4)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*decalalivetime[i]*distancemult*.25);
+ if(decalalivetime[i]>58)glColor4f(decalbrightness[i],decalbrightness[i],decalbrightness[i],decalopacity[i]*(60-decalalivetime[i])/2*distancemult);
+ }
+ }
+ lasttype=decaltype[i];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glBegin(GL_TRIANGLES);
+ for(int j=0;j<3;j++)
+ {
+ glTexCoord2f(decaltexcoords[i][j][0], decaltexcoords[i][j][1]); glVertex3f(decalvertex[i][j].x,decalvertex[i][j].y,decalvertex[i][j].z);
+ }
+ glEnd();
+ glPopMatrix();
+ }
+ for(i=numdecals-1;i>=0;i--){
+ decalalivetime[i]+=multiplier;
+ if(decaltype[i]==blooddecalslow)decalalivetime[i]-=multiplier*2/3;
+ if(decaltype[i]==blooddecalfast)decalalivetime[i]+=multiplier*4;
+ if(decaltype[i]==shadowdecal)DeleteDecal(i);
+ if(decaltype[i]==footprintdecal&&decalalivetime[i]>=5)DeleteDecal(i);
+ if(decaltype[i]==bodyprintdecal&&decalalivetime[i]>=5)DeleteDecal(i);
+ if((decaltype[i]==blooddecal||decaltype[i]==blooddecalfast||decaltype[i]==blooddecalslow)&&decalalivetime[i]>=60)DeleteDecal(i);
+ }
+ glAlphaFunc(GL_GREATER, 0.0001);
+ }
+}
+
+void Terrain::AddObject(XYZ where, float radius, int id)
+{
+ bool done;
+ int i,j;
+ XYZ points[4];
+ if(id>=0&&id<10000)
+ for(i=0;i<subdivision;i++){
+ for(j=0;j<subdivision;j++){
+ if(patchobjectnum[i][j]<300-1){
+ done=0;
+ points[0].x=(size/subdivision)*i;
+ points[0].z=(size/subdivision)*j;
+ points[0].y=heightmap[(int)points[0].x][(int)points[0].z];
+ points[1].x=(size/subdivision)*(i+1);
+ points[1].z=(size/subdivision)*j;
+ points[1].y=heightmap[(int)points[1].x][(int)points[1].z];
+ points[2].x=(size/subdivision)*(i+1);
+ points[2].z=(size/subdivision)*(j+1);
+ points[2].y=heightmap[(int)points[2].x][(int)points[2].z];
+ points[3].x=(size/subdivision)*i;
+ points[3].z=(size/subdivision)*(j+1);
+ points[3].y=heightmap[(int)points[3].x][(int)points[3].z];
+ points[0]*=scale*terraindetail;
+ points[1]*=scale*terraindetail;
+ points[2]*=scale*terraindetail;
+ points[3]*=scale*terraindetail;
+ if(!done&&where.x+radius>points[0].x&&where.x-radius<points[2].x&&where.z+radius>points[0].z&&where.z-radius<points[2].z){
+ patchobjects[i][j][patchobjectnum[i][j]]=id;
+ patchobjectnum[i][j]++;
+ done=1;
+ }
+ }
+ }
+ }
+}
+
+void Terrain::DeleteDecal(int which)
+{
+ if(decals){
+ decaltype[which]=decaltype[numdecals-1];
+ decalposition[which]=decalposition[numdecals-1];
+ for(int i=0;i<3;i++){
+ decalvertex[which][i]=decalvertex[numdecals-1][i];
+ decaltexcoords[which][i][0]=decaltexcoords[numdecals-1][i][0];
+ decaltexcoords[which][i][1]=decaltexcoords[numdecals-1][i][1];
+ }
+ decalrotation[which]=decalrotation[numdecals-1];
+ decalalivetime[which]=decalalivetime[numdecals-1];
+ decalopacity[which]=decalopacity[numdecals-1];
+ decalbrightness[which]=decalbrightness[numdecals-1];
+ numdecals--;
+ }
+}
+
+void Terrain::MakeDecal(int type, XYZ where, float size, float opacity, float rotation){
+ if(decals){
+ if(opacity>0&&size>0){
+ static int patchx[4];
+ static int patchy[4];
+
+ decaltexcoords[numdecals][0][0]=1;
+ decaltexcoords[numdecals][0][1]=0;
+
+ patchx[0]=(where.x+size)/scale;
+ patchx[1]=(where.x-size)/scale;
+ patchx[2]=(where.x-size)/scale;
+ patchx[3]=(where.x+size)/scale;
+
+ patchy[0]=(where.z-size)/scale;
+ patchy[1]=(where.z-size)/scale;
+ patchy[2]=(where.z+size)/scale;
+ patchy[3]=(where.z+size)/scale;
+
+ /*if(patchx[1]<subdivision-1&&patchy[1]<subdivision-1&&patchx[1]>0&&patchy[1]>0)
+ if(patchx[2]<subdivision-1&&patchy[2]<subdivision-1&&patchx[2]>0&&patchy[2]>0)
+ if(patchx[3]<subdivision-1&&patchy[3]<subdivision-1&&patchx[3]>0&&patchy[3]>0)
+ if(patchx[0]<subdivision-1&&patchy[0]<subdivision-1&&patchx[0]>0&&patchy[0]>0){
+ */
+ if((patchx[0]!=patchx[1]||patchy[0]!=patchy[1])&&(patchx[0]!=patchx[2]||patchy[0]!=patchy[2])&&(patchx[0]!=patchx[3]||patchy[0]!=patchy[3])){
+ MakeDecalLock(type,where,patchx[0],patchy[0],size,opacity,rotation);
+ }
+
+ if((patchx[1]!=patchx[2]||patchy[1]!=patchy[2])&&(patchx[1]!=patchx[3]||patchy[1]!=patchy[3])){
+ MakeDecalLock(type,where,patchx[1],patchy[1],size,opacity,rotation);
+ }
+
+ if((patchx[2]!=patchx[3]||patchy[2]!=patchy[3])){
+ MakeDecalLock(type,where,patchx[2],patchy[2],size,opacity,rotation);
+ }
+ MakeDecalLock(type,where,patchx[3],patchy[3],size,opacity,rotation);
+ }
+ }
+ //}
+}
+
+void Terrain::MakeDecalLock(int type, XYZ where,int whichx, int whichy, float size, float opacity, float rotation){
+ if(decals){
+ static float placex,placez;
+ static XYZ rot;
+
+ float decalbright;
+
+ rot=getLighting(where.x,where.z);
+ decalbrightness[numdecals]=(rot.x+rot.y+rot.z)/3;
+ if(decalbrightness[numdecals]<.4)decalbrightness[numdecals]=.4;
+
+ //if(type==blooddecal||type==blooddecalfast||type==blooddecalslow){
+ if(environment==grassyenvironment){
+ decalbrightness[numdecals]*=.6;
+ }
+ //}
+
+ if(decalbrightness[numdecals]>1)decalbrightness[numdecals]=1;
+ decalbright=decalbrightness[numdecals];
+
+ decalposition[numdecals]=where;
+ decaltype[numdecals]=type;
+ decalopacity[numdecals]=opacity;
+ decalrotation[numdecals]=rotation;
+ decalalivetime[numdecals]=0;
+
+ placex=(float)whichx*scale+scale;
+ placez=(float)whichy*scale;
+
+ decaltexcoords[numdecals][0][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][0].x=placex;
+ decalvertex[numdecals][0].z=placez;
+ decalvertex[numdecals][0].y=heightmap[whichx+1][whichy]*scale+.01;
+
+
+ placex=(float)whichx*scale+scale;
+ placez=(float)whichy*scale+scale;
+
+ decaltexcoords[numdecals][1][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][1].x=placex;
+ decalvertex[numdecals][1].z=placez;
+ decalvertex[numdecals][1].y=heightmap[whichx+1][whichy+1]*scale+.01;
+
+
+ placex=(float)whichx*scale;
+ placez=(float)whichy*scale+scale;
+
+ decaltexcoords[numdecals][2][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][2].x=placex;
+ decalvertex[numdecals][2].z=placez;
+ decalvertex[numdecals][2].y=heightmap[whichx][whichy+1]*scale+.01;
+
+ if(decalrotation[numdecals]){
+ for(int i=0;i<3;i++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][i][0]-.5;
+ rot.z=decaltexcoords[numdecals][i][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][i][0]=rot.x+.5;
+ decaltexcoords[numdecals][i][1]=rot.z+.5;
+ }
+ }
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ if(numdecals<max_decals-1)numdecals++;
+
+ decalbrightness[numdecals]=decalbright;
+
+ decalposition[numdecals]=where;
+ decaltype[numdecals]=type;
+ decalopacity[numdecals]=opacity;
+ decalrotation[numdecals]=rotation;
+ decalalivetime[numdecals]=0;
+
+ placex=(float)whichx*scale+scale;
+ placez=(float)whichy*scale;
+
+ decaltexcoords[numdecals][0][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][0][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][0].x=placex;
+ decalvertex[numdecals][0].z=placez;
+ decalvertex[numdecals][0].y=heightmap[whichx+1][whichy]*scale+.01;
+
+
+ placex=(float)whichx*scale;
+ placez=(float)whichy*scale;
+
+ decaltexcoords[numdecals][1][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][1][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][1].x=placex;
+ decalvertex[numdecals][1].z=placez;
+ decalvertex[numdecals][1].y=heightmap[whichx][whichy]*scale+.01;
+
+
+ placex=(float)whichx*scale;
+ placez=(float)whichy*scale+scale;
+
+ decaltexcoords[numdecals][2][0]=(placex-where.x)/size/2+.5;
+ decaltexcoords[numdecals][2][1]=(placez-where.z)/size/2+.5;
+
+ decalvertex[numdecals][2].x=placex;
+ decalvertex[numdecals][2].z=placez;
+ decalvertex[numdecals][2].y=heightmap[whichx][whichy+1]*scale+.01;
+
+ if(decalrotation[numdecals]){
+ for(int i=0;i<3;i++){
+ rot.y=0;
+ rot.x=decaltexcoords[numdecals][i][0]-.5;
+ rot.z=decaltexcoords[numdecals][i][1]-.5;
+ rot=DoRotation(rot,0,-decalrotation[numdecals],0);
+ decaltexcoords[numdecals][i][0]=rot.x+.5;
+ decaltexcoords[numdecals][i][1]=rot.z+.5;
+ }
+ }
+
+ if(!(decaltexcoords[numdecals][0][0]<0&&decaltexcoords[numdecals][1][0]<0&&decaltexcoords[numdecals][2][0]<0))
+ if(!(decaltexcoords[numdecals][0][1]<0&&decaltexcoords[numdecals][1][1]<0&&decaltexcoords[numdecals][2][1]<0))
+ if(!(decaltexcoords[numdecals][0][0]>1&&decaltexcoords[numdecals][1][0]>1&&decaltexcoords[numdecals][2][0]>1))
+ if(!(decaltexcoords[numdecals][0][1]>1&&decaltexcoords[numdecals][1][1]>1&&decaltexcoords[numdecals][2][1]>1))
+ if(numdecals<max_decals-1)numdecals++;
+ }
+}
+
+void Terrain::DoLighting()
+{
+ static int i,j,k,todivide;
+ static float brightness, total;
+ static XYZ blank, terrainpoint,lightloc;
+ lightloc=light.location;
+ Normalise(&lightloc);
+ //Calculate shadows
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ terrainpoint.x=(float)i*scale;
+ terrainpoint.z=(float)j*scale;
+ terrainpoint.y=heightmap[i][j]*scale+.1;
+ /*brightness=0;
+ if(lineTerrain(lightlocation*10+terrainpoint,terrainpoint,&blank)==-1)
+ */
+ brightness=dotproduct(&lightloc,&normals[i][j]);
+
+ if(brightness>1)brightness=1;
+ if(brightness<0)brightness=0;
+
+ colors[i][j][0]=light.color[0]*brightness+light.ambient[0];
+ colors[i][j][1]=light.color[1]*brightness+light.ambient[1];
+ colors[i][j][2]=light.color[2]*brightness+light.ambient[2];
+
+ if(colors[i][j][0]>1)colors[i][j][0]=1;
+ if(colors[i][j][1]>1)colors[i][j][1]=1;
+ if(colors[i][j][2]>1)colors[i][j][2]=1;
+ if(colors[i][j][0]<0)colors[i][j][0]=0;
+ if(colors[i][j][1]<0)colors[i][j][1]=0;
+ if(colors[i][j][2]<0)colors[i][j][2]=0;
+ }
+ }
+
+ //Smooth shadows
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ for(k=0;k<3;k++){
+ total=0;
+ todivide=0;
+ if(i!=0){ total+=colors[j][i-1][k]; todivide++;}
+ if(i!=size-1){ total+=colors[j][i+1][k]; todivide++;}
+ if(j!=0){ total+=colors[j-1][i][k]; todivide++;}
+ if(j!=size-1){ total+=colors[j+1][i][k]; todivide++;}
+ if(i!=0&&j!=0){ total+=colors[j-1][i-1][k]; todivide++;}
+ if(i!=size-1&&j!=0){ total+=colors[j-1][i+1][k]; todivide++;}
+ if(j!=size-1&&i!=size-1){ total+=colors[j+1][i+1][k]; todivide++;}
+ if(j!=size-1&&i!=0){ total+=colors[j+1][i-1][k]; todivide++;}
+ total+=colors[j][i][k]; todivide++;
+
+ colors[j][i][k]=total/todivide;
+ }
+ }
+ }
+}
+
+void Terrain::DoShadows()
+{
+ static int i,j,k,l,todivide;
+ static float brightness, total;
+ static XYZ testpoint,testpoint2, terrainpoint,lightloc,col;
+ lightloc=light.location;
+ if(!skyboxtexture){
+ lightloc.x=0;
+ lightloc.z=0;
+ }
+ if(skyboxtexture&&tutoriallevel){
+ lightloc.x*=.4;
+ lightloc.z*=.4;
+ }
+ int patchx,patchz;
+ float shadowed;
+ Normalise(&lightloc);
+ //Calculate shadows
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ terrainpoint.x=(float)(i)*scale;
+ terrainpoint.z=(float)(j)*scale;
+ terrainpoint.y=heightmap[i][j]*scale;
+
+ shadowed=0;
+ patchx=(float)(i)*subdivision/size;
+ patchz=(float)(j)*subdivision/size;
+ if(patchobjectnum[patchx][patchz]){
+ for(k=0;k<patchobjectnum[patchx][patchz];k++){
+ l=patchobjects[patchx][patchz][k];
+ if(objects.type[l]!=treetrunktype){
+ testpoint=terrainpoint;
+ testpoint2=terrainpoint+lightloc*50*(1-shadowed);
+ if(objects.model[l].LineCheck(&testpoint,&testpoint2,&col,&objects.position[l],&objects.rotation[l])!=-1){
+ shadowed=1-(findDistance(&terrainpoint,&col)/50);
+ }
+ }
+ }
+ if(visibleloading)pgame->LoadingScreen();
+ }
+ brightness=dotproduct(&lightloc,&normals[i][j]);
+ if(shadowed)brightness*=1-shadowed;
+
+ if(brightness>1)brightness=1;
+ if(brightness<0)brightness=0;
+
+ colors[i][j][0]=light.color[0]*brightness+light.ambient[0];
+ colors[i][j][1]=light.color[1]*brightness+light.ambient[1];
+ colors[i][j][2]=light.color[2]*brightness+light.ambient[2];
+
+ if(colors[i][j][0]>1)colors[i][j][0]=1;
+ if(colors[i][j][1]>1)colors[i][j][1]=1;
+ if(colors[i][j][2]>1)colors[i][j][2]=1;
+ if(colors[i][j][0]<0)colors[i][j][0]=0;
+ if(colors[i][j][1]<0)colors[i][j][1]=0;
+ if(colors[i][j][2]<0)colors[i][j][2]=0;
+ }
+ }
+
+ if(visibleloading)pgame->LoadingScreen();
+
+ //Smooth shadows
+ for(i=0;i<size;i++){
+ for(j=0;j<size;j++){
+ for(k=0;k<3;k++){
+ total=0;
+ todivide=0;
+ if(i!=0){ total+=colors[j][i-1][k]; todivide++;}
+ if(i!=size-1){ total+=colors[j][i+1][k]; todivide++;}
+ if(j!=0){ total+=colors[j-1][i][k]; todivide++;}
+ if(j!=size-1){ total+=colors[j+1][i][k]; todivide++;}
+ if(i!=0&&j!=0){ total+=colors[j-1][i-1][k]; todivide++;}
+ if(i!=size-1&&j!=0){ total+=colors[j-1][i+1][k]; todivide++;}
+ if(j!=size-1&&i!=size-1){ total+=colors[j+1][i+1][k]; todivide++;}
+ if(j!=size-1&&i!=0){ total+=colors[j+1][i-1][k]; todivide++;}
+ total+=colors[j][i][k]; todivide++;
+
+ colors[j][i][k]=total/todivide;
+ }
+ }
+ }
+
+ for(i=0;i<subdivision;i++){
+ for(j=0;j<subdivision;j++){
+ UpdateVertexArray(i,j);
+ }
+ }
+}
+
+Terrain::Terrain()
+{
+ bloodtexture = 0;
+ bloodtexture2 = 0;
+ shadowtexture = 0;
+ footprinttexture = 0;
+ bodyprinttexture = 0;
+ breaktexture = 0;
+ terraintexture = 0;
+ size = 0;
+
+ memset(patchobjectnum, 0, sizeof(patchobjectnum));
+ memset(patchobjects, 0, sizeof(patchobjects));
+
+ scale = 0;
+ type = 0;
+ memset(heightmap, 0, sizeof(heightmap));
+ memset(normals, 0, sizeof(normals));
+ memset(facenormals, 0, sizeof(facenormals));
+ memset(triangles, 0, sizeof(triangles));
+ memset(colors, 0, sizeof(colors));
+ memset(opacityother, 0, sizeof(opacityother));
+ memset(texoffsetx, 0, sizeof(texoffsetx));
+ memset(texoffsety, 0, sizeof(texoffsety));
+ memset(numtris, 0, sizeof(numtris));
+ memset(textureness, 0, sizeof(textureness));
+
+ memset(vArray, 0, sizeof(vArray));
+
+ memset(visible, 0, sizeof(visible));
+ memset(avgypatch, 0, sizeof(avgypatch));
+ memset(maxypatch, 0, sizeof(maxypatch));
+ memset(minypatch, 0, sizeof(minypatch));
+ memset(heightypatch, 0, sizeof(heightypatch));
+
+ patch_elements = 0;
+
+ memset(decaltexcoords, 0, sizeof(decaltexcoords));
+ memset(decalvertex, 0, sizeof(decalvertex));
+ memset(decaltype, 0, sizeof(decaltype));
+ memset(decalopacity, 0, sizeof(decalopacity));
+ memset(decalrotation, 0, sizeof(decalrotation));
+ memset(decalalivetime, 0, sizeof(decalalivetime));
+ memset(decalbrightness, 0, sizeof(decalbrightness));
+ memset(decalposition, 0, sizeof(decalposition));
+ numdecals = 0;
+}
+Terrain::~Terrain()
+{
+ if(terraintexture)glDeleteTextures( 1, (const unsigned long *)&terraintexture );
+ if(shadowtexture) glDeleteTextures( 1, (const unsigned long *)&shadowtexture );
+ if(bodyprinttexture) glDeleteTextures( 1, (const unsigned long *)&bodyprinttexture );
+ if(footprinttexture) glDeleteTextures( 1, (const unsigned long *)&footprinttexture );
+ if(bloodtexture) glDeleteTextures( 1, (const unsigned long *)&bloodtexture );
+ if(bloodtexture2) glDeleteTextures( 1, (const unsigned long *)&bloodtexture2 );
+ if(breaktexture) glDeleteTextures( 1, (const unsigned long *)&breaktexture );
+}
--- /dev/null
+#ifndef _TERRAIN_H_
+#define _TERRAIN_H_
+
+#include "gl.h"
+#include "Frustum.h"
+#include "Lights.h"
+#include "TGALoader.h"
+#include "Quaternions.h"
+#include "Quaternions.h"
+
+#define max_terrain_size 256
+#define curr_terrain_size size
+#define subdivision 64
+#define max_patch_elements (max_terrain_size/subdivision)*(max_terrain_size/subdivision)*54
+
+#define allfirst 0
+#define mixed 1
+#define allsecond 2
+
+#define max_decals 1000
+
+#define shadowdecal 0
+#define footprintdecal 1
+#define blooddecal 2
+#define blooddecalfast 3
+#define shadowdecalpermanent 4
+#define breakdecal 5
+#define blooddecalslow 6
+#define bodyprintdecal 7
+
+#define snowyenvironment 0
+#define grassyenvironment 1
+#define desertenvironment 2
+//
+// Model Structures
+//
+
+class Terrain{
+public:
+ GLuint bloodtexture;
+ GLuint bloodtexture2;
+ GLuint shadowtexture;
+ GLuint footprinttexture;
+ GLuint bodyprinttexture;
+ GLuint breaktexture;
+ GLuint terraintexture;
+ short size;
+
+ int patchobjectnum[subdivision][subdivision];
+ int patchobjects[subdivision][subdivision][300];
+
+ float scale;
+ int type;
+ float heightmap[max_terrain_size+1][max_terrain_size+1];
+ XYZ normals[max_terrain_size][max_terrain_size];
+ XYZ facenormals[max_terrain_size][max_terrain_size];
+ XYZ triangles[(max_terrain_size-1)*(max_terrain_size-1)*2][3];
+ float colors[max_terrain_size][max_terrain_size][4];
+ float opacityother[max_terrain_size][max_terrain_size];
+ float texoffsetx[max_terrain_size][max_terrain_size];
+ float texoffsety[max_terrain_size][max_terrain_size];
+ int numtris[subdivision][subdivision];
+ int textureness[subdivision][subdivision];
+
+ GLfloat vArray[(max_patch_elements)*subdivision*subdivision];
+
+ bool visible[subdivision][subdivision];
+ float avgypatch[subdivision][subdivision];
+ float maxypatch[subdivision][subdivision];
+ float minypatch[subdivision][subdivision];
+ float heightypatch[subdivision][subdivision];
+
+ int patch_elements;
+
+ float decaltexcoords[max_decals][3][2];
+ XYZ decalvertex[max_decals][3];
+ int decaltype[max_decals];
+ float decalopacity[max_decals];
+ float decalrotation[max_decals];
+ float decalalivetime[max_decals];
+ float decalbrightness[max_decals];
+ XYZ decalposition[max_decals];
+ int numdecals;
+
+ void AddObject(XYZ where, float radius,int id);
+ void DeleteDecal(int which);
+ void MakeDecal(int type, XYZ where, float size, float opacity, float rotation);
+ void MakeDecalLock(int type, XYZ where, int whichx, int whichy, float size, float opacity, float rotation);
+ int lineTerrain(XYZ p1,XYZ p2, XYZ *p);
+ float getHeight(float pointx, float pointz);
+ float getHeightExtrude(float pointx, float pointz,float point2x, float point2z);
+ float getOpacity(float pointx, float pointz);
+ XYZ getLighting(float pointx, float pointz);
+ XYZ getNormal(float pointx, float pointz);
+ void UpdateVertexArray(int whichx, int whichy);
+ void UpdateTransparency(int whichx, int whichy);
+ void UpdateTransparencyother(int whichx, int whichy);
+ void UpdateTransparencyotherother(int whichx, int whichy);
+ bool load(char *fileName);
+ void CalculateNormals();
+ void drawdecals();
+ void draw(int layer);
+ void drawpatch(int whichx, int whichy, float opacity);
+ void drawpatchother(int whichx, int whichy, float opacity);
+ void drawpatchotherother(int whichx, int whichy, float opacity);
+ void DoLighting();
+ void DoShadows();
+
+ Terrain();
+ ~Terrain();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "Text.h"
+#include "Game.h"
+extern TGAImageRec texture;
+
+void Text::LoadFontTexture(char *fileName)
+{
+ GLuint type;
+
+ LOGFUNC;
+
+ LOG(std::string("Loading font texture...") + fileName);
+
+ Game::LoadTexture(fileName, &FontTexture, false, false);
+/*
+ //Load Image
+ //LoadTGA( fileName );
+ unsigned char fileNamep[256];
+ CopyCStringToPascal(fileName,fileNamep);
+ //Load Image
+ upload_image( fileNamep ,1);
+
+ //Is it valid?
+ if(1==1){
+ //Alpha channel?
+ if ( texture.bpp == 24 )
+ type = GL_RGB;
+ else
+ type = GL_RGBA;
+
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ if(!FontTexture)glGenTextures( 1, &FontTexture );
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+
+ glBindTexture( GL_TEXTURE_2D, FontTexture);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ gluBuild2DMipmaps( GL_TEXTURE_2D, type, texture.sizeX, texture.sizeY, type, GL_UNSIGNED_BYTE, texture.data );
+ }
+*/
+ if (base)
+ {
+ glDeleteLists(base, 512);
+ base = 0;
+ }
+}
+
+void Text::BuildFont() // Build Our Font Display List
+{
+ float cx; // Holds Our X Character Coord
+ float cy; // Holds Our Y Character Coord
+ int loop;
+
+ LOGFUNC;
+
+ if (base)
+ {
+ LOG("Font already created...");
+ return;
+ }
+
+// base=glGenLists(256); // Creating 256 Display Lists
+ base=glGenLists(512); // Creating 256 Display Lists
+ glBindTexture(GL_TEXTURE_2D, FontTexture); // Select Our Font Texture
+ for (loop=0; loop<256; loop++) // Loop Through All 256 Lists
+ {
+ cx=float(loop%16)/16.0f; // X Position Of Current Character
+ cy=float(loop/16)/16.0f; // Y Position Of Current Character
+
+ glNewList(base+loop,GL_COMPILE); // Start Building A List
+ glBegin(GL_QUADS); // Use A Quad For Each Character
+ glTexCoord2f(cx,1-cy-0.0625f+.001); // Texture Coord (Bottom Left)
+ glVertex2i(0,0); // Vertex Coord (Bottom Left)
+ glTexCoord2f(cx+0.0625f,1-cy-0.0625f+.001); // Texture Coord (Bottom Right)
+ glVertex2i(16,0); // Vertex Coord (Bottom Right)
+ glTexCoord2f(cx+0.0625f,1-cy-.001); // Texture Coord (Top Right)
+ glVertex2i(16,16); // Vertex Coord (Top Right)
+ glTexCoord2f(cx,1-cy-+.001); // Texture Coord (Top Left)
+ glVertex2i(0,16); // Vertex Coord (Top Left)
+ glEnd(); // Done Building Our Quad (Character)
+ glTranslated(10,0,0); // Move To The Right Of The Character
+ glEndList(); // Done Building The Display List
+ } // Loop Until All 256 Are Built
+ for (loop=256; loop<512; loop++) // Loop Through All 256 Lists
+ {
+ cx=float((loop-256)%16)/16.0f; // X Position Of Current Character
+ cy=float((loop-256)/16)/16.0f; // Y Position Of Current Character
+
+ glNewList(base+loop,GL_COMPILE); // Start Building A List
+ glBegin(GL_QUADS); // Use A Quad For Each Character
+ glTexCoord2f(cx,1-cy-0.0625f+.001); // Texture Coord (Bottom Left)
+ glVertex2i(0,0); // Vertex Coord (Bottom Left)
+ glTexCoord2f(cx+0.0625f,1-cy-0.0625f+.001); // Texture Coord (Bottom Right)
+ glVertex2i(16,0); // Vertex Coord (Bottom Right)
+ glTexCoord2f(cx+0.0625f,1-cy-.001); // Texture Coord (Top Right)
+ glVertex2i(16,16); // Vertex Coord (Top Right)
+ glTexCoord2f(cx,1-cy-+.001); // Texture Coord (Top Left)
+ glVertex2i(0,16); // Vertex Coord (Top Left)
+ glEnd(); // Done Building Our Quad (Character)
+ glTranslated(8,0,0); // Move To The Right Of The Character
+ glEndList(); // Done Building The Display List
+ } // Loop Until All 256 Are Built
+}
+
+void Text::glPrint(float x, float y, char *string, int set, float size, float width, float height) // Where The Printing Happens
+{
+ if (set>1)
+ {
+ set=1;
+ }
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glBindTexture(GL_TEXTURE_2D, FontTexture); // Select Our Font Texture
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,width,0,height,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity();
+ glTranslated(x,y,0); // Position The Text (0,0 - Bottom Left)
+ glScalef(size,size,1); // Reset The Modelview Matrix
+ glListBase(base-32+(128*set)); // Choose The Font Set (0 or 1)
+ glCallLists(strlen(string),GL_BYTE,string); // Write The Text To The Screen
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+}
+
+void Text::glPrint(float x, float y, char *string, int set, float size, float width, float height,int start,int end) // Where The Printing Happens
+{
+ if (set>1)
+ {
+ set=1;
+ }
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glBindTexture(GL_TEXTURE_2D, FontTexture); // Select Our Font Texture
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,width,0,height,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity();
+ glTranslated(x,y,0); // Position The Text (0,0 - Bottom Left)
+ glScalef(size,size,1); // Reset The Modelview Matrix
+ glListBase(base-32+(128*set)); // Choose The Font Set (0 or 1)
+ glCallLists(end-start,GL_BYTE,&string[start]); // Write The Text To The Screen
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+}
+
+
+void Text::glPrintOutline(float x, float y, char *string, int set, float size, float width, float height) // Where The Printing Happens
+{
+ if (set>1)
+ {
+ set=1;
+ }
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glBindTexture(GL_TEXTURE_2D, FontTexture); // Select Our Font Texture
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,width,0,height,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity();
+ glTranslated(x,y,0); // Position The Text (0,0 - Bottom Left)
+ glScalef(size,size,1); // Reset The Modelview Matrix
+ glListBase(base-32+(128*set)+256); // Choose The Font Set (0 or 1)
+ glCallLists(strlen(string),GL_BYTE,string); // Write The Text To The Screen
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+}
+
+void Text::glPrintOutline(float x, float y, char *string, int set, float size, float width, float height,int start,int end) // Where The Printing Happens
+{
+ if (set>1)
+ {
+ set=1;
+ }
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+ glBindTexture(GL_TEXTURE_2D, FontTexture); // Select Our Font Texture
+ glDisable(GL_DEPTH_TEST); // Disables Depth Testing
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPushMatrix(); // Store The Projection Matrix
+ glLoadIdentity(); // Reset The Projection Matrix
+ glOrtho(0,width,0,height,-100,100); // Set Up An Ortho Screen
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix(); // Store The Modelview Matrix
+ glLoadIdentity();
+ glTranslated(x,y,0); // Position The Text (0,0 - Bottom Left)
+ glScalef(size,size,1); // Reset The Modelview Matrix
+ glListBase(base-32+(128*set)+256); // Choose The Font Set (0 or 1)
+ glCallLists(end-start,GL_BYTE,&string[start]); // Write The Text To The Screen
+ glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPopMatrix(); // Restore The Old Projection Matrix
+ glEnable(GL_DEPTH_TEST); // Enables Depth Testing
+ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
+}
+
+void Text::glPrintOutlined(float x, float y, char *string, int set, float size, float width, float height) // Where The Printing Happens
+{
+ glColor4f(0,0,0,1);
+ glPrintOutline( x-2*size, y-2*size, string, set, size*2.5/2, width, height);
+ glColor4f(1,1,1,1);
+ glPrint( x, y, string, set, size, width, height);
+}
+
+void Text::glPrintOutlined(float r, float g, float b, float x, float y, char *string, int set, float size, float width, float height) // Where The Printing Happens
+{
+ glColor4f(0,0,0,1);
+ glPrintOutline( x-2*size, y-2*size, string, set, size*2.5/2, width, height);
+ glColor4f(r,g,b,1);
+ glPrint( x, y, string, set, size, width, height);
+}
+
+Text::Text()
+{
+ base = 0;
+ FontTexture = 0;
+}
+Text::~Text()
+{
+ if (base)
+ {
+ glDeleteLists(base, 512);
+ base = 0;
+ }
+ if (FontTexture) glDeleteTextures( 1, (const unsigned long *)&FontTexture );
+}
--- /dev/null
+#ifndef _TEXT_H_
+#define _TEXT_H_
+
+
+/**> HEADER FILES <**/
+#include "Quaternions.h"
+//#include "Files.h"
+#include "Quaternions.h"
+#include "gl.h"
+#include "TGALoader.h"
+
+class Text{
+public:
+ GLuint FontTexture;
+ GLuint base;
+
+ void LoadFontTexture(char *fileName);
+ void BuildFont();
+ void glPrint(float x, float y, char *string, int set, float size, float width, float height);
+ void glPrintOutline(float x, float y, char *string, int set, float size, float width, float height);
+ void glPrint(float x, float y, char *string, int set, float size, float width, float height,int start,int end);
+ void glPrintOutline(float x, float y, char *string, int set, float size, float width, float height,int start,int end);
+ void glPrintOutlined(float x, float y, char *string, int set, float size, float width, float height);
+ void glPrintOutlined(float r, float g, float b, float x, float y, char *string, int set, float size, float width, float height);
+
+ Text();
+ ~Text();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "Weapons.h"
+
+extern float multiplier;
+extern Animation animation[animation_count];
+extern FSOUND_SAMPLE *samp[100];
+extern int channels[100];
+extern Terrain terrain;
+extern float gravity;
+extern int environment;
+extern Sprites sprites;
+extern int detail;
+extern FRUSTUM frustum;
+extern XYZ viewer;
+extern float realmultiplier;
+extern int slomo;
+extern float slomodelay;
+extern bool cellophane;
+extern float texdetail;
+extern GLubyte bloodText[512*512*3];
+extern int bloodtoggle;
+extern Objects objects;
+extern bool osx;
+extern bool autoslomo;
+extern float camerashake;
+extern float woozy;
+extern float terraindetail;
+extern float viewdistance;
+extern float blackout;
+extern int difficulty;
+extern Person player[maxplayers];
+extern int numplayers;
+extern bool freeze;
+extern int bonus;
+extern float bonusvalue;
+extern float bonustotal;
+extern float bonustime;
+extern int tutoriallevel;
+extern int numthrowkill;
+extern "C" void PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+
+void Weapons::DoStuff(){
+ static int i,whichpatchx,whichpatchz,j,k,whichhit,m;
+ static XYZ start,end,colpoint,normalrot,footvel,footpoint;
+ static XYZ terrainnormal;
+ static XYZ vel;
+ static XYZ midp;
+ static XYZ newpoint1,newpoint2;
+ static float friction=3.5;
+ static float elasticity=.4;
+ static XYZ bounceness;
+ static float frictionness;
+ static float moveamount;
+ int closestline;
+ static float closestdistance;
+ static float distance;
+ static XYZ point[3];
+ static XYZ closestpoint;
+ static XYZ closestswordpoint;
+ static XYZ extramove;
+ static float proportion;
+ static float tempmult;
+
+ //Move
+
+ for(i=0;i<numweapons;i++){
+ if(owner[i]!=-1){
+ oldowner[i]=owner[i];
+ }
+ if(damage[i]>=2&&type[i]==staff&&owner[i]!=-1){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=tippoint[i].x;
+ gLoc[1]=tippoint[i].y;
+ gLoc[2]=tippoint[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( staffbreaksound, samp[staffbreaksound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[staffbreaksound], gLoc, vel);
+ FSOUND_SetVolume(channels[staffbreaksound], 256);
+ FSOUND_SetPaused(channels[staffbreaksound], FALSE);
+ XYZ tempvel;
+ XYZ speed;
+ //speed=(tippoint[i]-oldtippoint[i])/multiplier/6;
+ speed=0;
+ /*for(j=0;j<10;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ tempvel+=speed;
+ sprites.MakeSprite(cloudimpactsprite, position[i]+(tippoint[i]-position[i])*((float)j-2)/8,tempvel*.5, 115/255,73/255,12/255, .15+float(abs(Random()%100)-50)/1000, .7);
+ }*/
+ for(j=0;j<40;j++){
+ tempvel.x=float(abs(Random()%100)-50)/20;
+ tempvel.y=float(abs(Random()%100)-50)/20;
+ tempvel.z=float(abs(Random()%100)-50)/20;
+ tempvel+=speed;
+ sprites.MakeSprite(splintersprite, position[i]+(tippoint[i]-position[i])*((float)j-8)/32,tempvel*.5, 115/255,73/255,12/255, .1, 1);
+ }
+ int tempowner;
+ tempowner=owner[i];
+ owner[i]=-1;
+ hitsomething[i]=0;
+ missed[i]=1;
+ freetime[i]=0;
+ firstfree[i]=1;
+ position[i]=0;
+ physics[i]=0;
+ if(tempowner!=-1){
+ player[tempowner].num_weapons--;
+ if(player[tempowner].num_weapons){
+ player[tempowner].weaponids[0]=player[tempowner].weaponids[player[tempowner].num_weapons];
+ if(player[tempowner].weaponstuck==player[tempowner].num_weapons)player[tempowner].weaponstuck=0;
+ }
+ player[tempowner].weaponactive=-1;
+ }
+ }
+ oldposition[i]=position[i];
+ oldtippoint[i]=tippoint[i];
+ if(owner[i]==-1&&(velocity[i].x||velocity[i].y||velocity[i].z)&&!physics[i]){
+ position[i]+=velocity[i]*multiplier;
+ tippoint[i]+=velocity[i]*multiplier;
+ whichpatchx=position[i].x/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=position[i].z/(terrain.size/subdivision*terrain.scale*terraindetail);
+ if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
+ for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][j];
+ start=oldtippoint[i];
+ end=tippoint[i];
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ if(objects.type[k]==treetrunktype){
+ objects.model[k].MakeDecal(breakdecal,DoRotation(colpoint-objects.position[k],0,-objects.rotation[k],0),.1,1,Random()%360);
+ normalrot=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0);
+ velocity[i]=0;
+ if(type[i]==knife)position[i]=colpoint-normalrot*.1;
+ if(type[i]==sword)position[i]=colpoint-normalrot*.2;
+ if(type[i]==staff)position[i]=colpoint-normalrot*.2;
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=0;
+ temppoint2=normalrot;
+ distance=findDistance(&temppoint1,&temppoint2);
+ rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ rotation1[i]*=360/6.28;
+ if(temppoint1.x>temppoint2.x)rotation1[i]=360-rotation1[i];
+
+ rotation3[i]=0;
+ smallrotation[i]=90;
+ smallrotation2[i]=0;
+ bigtilt[i]=0;
+ bigtilt2[i]=0;
+ bigrotation[i]=0;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+
+ bloody[i]=0;
+
+ sprites.MakeSprite(cloudimpactsprite, position[i],velocity[i], 1,1,1, .8, .3);
+ }
+ else {
+ physics[i]=1;
+ firstfree[i]=1;
+ position[i]-=velocity[i]*multiplier;
+ tippoint[i]-=velocity[i]*multiplier;
+ tipvelocity[i]=velocity[i];
+ }
+ }
+ }
+ }
+ if(velocity[i].x||velocity[i].y||velocity[i].z)
+ for(j=0;j<numplayers;j++){
+ footvel=0;
+ footpoint=DoRotation((player[j].skeleton.joints[player[j].skeleton.jointlabels[abdomen]].position+player[j].skeleton.joints[player[j].skeleton.jointlabels[neck]].position)/2,0,player[j].rotation,0)*player[j].scale+player[j].coords;
+ if(owner[i]==-1&&findDistancefastflat(&position[i],&player[j].coords)<1.5&&findDistancefast(&position[i],&player[j].coords)<4&&player[j].weaponstuck==-1&&!player[j].skeleton.free&&j!=oldowner[i]){
+ if((player[j].aitype!=attacktypecutoff||abs(Random()%6)==0||(player[j].targetanimation!=backhandspringanim&&player[j].targetanimation!=rollanim&&player[j].targetanimation!=flipanim&&Random()%2==0))&&!missed[i]){
+ bool caught=0;
+ if((player[j].creature==wolftype&&Random()%3!=0&&player[j].weaponactive==-1&&(player[j].isIdle()||player[j].isRun()||player[j].targetanimation==walkanim))||(player[j].creature==rabbittype&&Random()%2==0&&player[j].aitype==attacktypecutoff&&player[j].weaponactive==-1)){
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=player[j].coords.x;
+ gLoc[1]=player[j].coords.y;
+ gLoc[2]=player[j].coords.z;
+ vel[0]=player[j].velocity.x;
+ vel[1]=player[j].velocity.y;
+ vel[2]=player[j].velocity.z;
+ PlaySoundEx( knifedrawsound, samp[knifedrawsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifedrawsound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifedrawsound], 128);
+ FSOUND_SetPaused(channels[knifedrawsound], FALSE);
+
+ player[j].weaponactive=0;
+ player[j].targetanimation=removeknifeanim;
+ player[j].targetframe=1;
+ player[j].target=1;
+ owner[i]=player[j].id;
+ if(player[j].num_weapons>0){
+ player[j].weaponids[player[j].num_weapons]=player[j].weaponids[0];
+ }
+ player[j].num_weapons++;
+ player[j].weaponids[0]=i;
+
+ player[j].aitype=attacktypecutoff;
+ }
+ else {
+ if(j!=0)numthrowkill++;
+ player[j].num_weapons++;
+ player[j].weaponstuck=player[j].num_weapons-1;
+ if(normaldotproduct(player[j].facing,velocity[i])>0)player[j].weaponstuckwhere=1;
+ else player[j].weaponstuckwhere=0;
+
+ player[j].weaponids[player[j].num_weapons-1]=i;
+
+ player[j].RagDoll(0);
+ player[j].skeleton.joints[player[j].skeleton.jointlabels[abdomen]].velocity+=velocity[i]*2;
+ player[j].skeleton.joints[player[j].skeleton.jointlabels[neck]].velocity+=velocity[i]*2;
+ player[j].skeleton.joints[player[j].skeleton.jointlabels[rightshoulder]].velocity+=velocity[i]*2;
+ player[j].skeleton.joints[player[j].skeleton.jointlabels[leftshoulder]].velocity+=velocity[i]*2;
+ //player[j].Puff(abdomen);
+ if(bloodtoggle&&tutoriallevel!=1)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,0,0, .8, .3);
+ if(tutoriallevel==1)sprites.MakeSprite(cloudimpactsprite, footpoint,footvel, 1,1,1, .8, .3);
+ footvel=tippoint[i]-position[i];
+ Normalise(&footvel);
+ if(bloodtoggle&&tutoriallevel!=1)sprites.MakeSprite(bloodflamesprite, footpoint,footvel*-1, 1,0,0, .6, 1);
+
+ if(tutoriallevel!=1){
+ if(player[j].weaponstuckwhere==0)player[j].DoBloodBig(2,205);
+ if(player[j].weaponstuckwhere==1)player[j].DoBloodBig(2,200);
+ player[j].damage+=200/player[j].armorhigh;
+ player[j].deathbleeding=1;
+ player[j].bloodloss+=(200+abs((float)(Random()%40))-20)/player[j].armorhigh;
+ owner[i]=j;
+ bloody[i]=2;
+ blooddrip[i]=5;
+ }
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( fleshstabsound, samp[fleshstabsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[fleshstabsound], gLoc, vel);
+ FSOUND_SetVolume(channels[fleshstabsound], 128);
+ FSOUND_SetPaused(channels[fleshstabsound], FALSE);
+
+ if(animation[player[0].targetanimation].height==highheight){
+ bonus=ninja;
+ bonustime=0;
+ bonusvalue=60;
+ }
+ else{
+ bonus=Bullseyebonus;
+ bonustime=0;
+ bonusvalue=30;
+ }
+ }
+ }
+ else missed[i]=1;
+ }
+ }
+ if(position[i].y<terrain.getHeight(position[i].x,position[i].z)){
+ if(terrain.getOpacity(position[i].x,position[i].z)<.2){
+ velocity[i]=0;
+ if(terrain.lineTerrain(oldposition[i],position[i],&colpoint)!=-1){
+ position[i]=colpoint*terrain.scale;
+ }
+ else position[i].y=terrain.getHeight(position[i].x,position[i].z);
+
+ terrain.MakeDecal(shadowdecalpermanent,position[i],.06,.5,0);
+ normalrot=terrain.getNormal(position[i].x,position[i].z)*-1;
+ velocity[i]=0;
+ //position[i]-=normalrot*.1;
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ GLfloat M[16];
+ glLoadIdentity();
+ glRotatef(bigrotation[i],0,1,0);
+ glRotatef(bigtilt2[i],1,0,0);
+ glRotatef(bigtilt[i],0,0,1);
+ glRotatef(-rotation1[i]+90,0,1,0);
+ glRotatef(-rotation2[i]+90,0,0,1);
+ glRotatef(-rotation3[i],0,1,0);
+ glRotatef(smallrotation[i],1,0,0);
+ glRotatef(smallrotation2[i],0,1,0);
+ glTranslatef(0,0,1);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ tippoint[i].x=M[12];
+ tippoint[i].y=M[13];
+ tippoint[i].z=M[14];
+ glPopMatrix();
+ position[i]-=tippoint[i]*.15;
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ rotation3[i]=0;
+ smallrotation[i]=90;
+ smallrotation2[i]=0;
+ bigtilt[i]=0;
+ bigtilt2[i]=0;
+ bigrotation[i]=0;
+
+ float gLoc[3];
+ float vel[3];
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( knifesheathesound, samp[knifesheathesound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[knifesheathesound], gLoc, vel);
+ FSOUND_SetVolume(channels[knifesheathesound], 128);
+ FSOUND_SetPaused(channels[knifesheathesound], FALSE);
+
+ XYZ terrainlight;
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ if(environment==snowyenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x,terrainlight.y,terrainlight.z, .5, .7);
+ }
+ else if(environment==grassyenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x*90/255,terrainlight.y*70/255,terrainlight.z*8/255, .5, .5);
+ }
+ else if(environment==desertenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x*190/255,terrainlight.y*170/255,terrainlight.z*108/255, .5, .7);
+ }
+
+ bloody[i]=0;
+ }
+ else {
+ physics[i]=1;
+ firstfree[i]=1;
+ position[i]-=velocity[i]*multiplier;
+ tippoint[i]-=velocity[i]*multiplier;
+ tipvelocity[i]=velocity[i];
+ }
+ }
+ if(velocity[i].x!=0||velocity[i].z!=0||velocity[i].y!=0){
+ velocity[i].y+=gravity*multiplier;
+
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=0;
+ temppoint2=velocity[i];
+ distance=findDistance(&temppoint1,&temppoint2);
+ rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ rotation1[i]*=360/6.28;
+ rotation3[i]=0;
+ smallrotation[i]=90;
+ smallrotation2[i]=0;
+ bigtilt[i]=0;
+ bigtilt2[i]=0;
+ bigrotation[i]=0;
+ if(temppoint1.x>temppoint2.x)rotation1[i]=360-rotation1[i];
+ }
+ }
+ //Sword physics
+ XYZ mid;
+ XYZ oldmid;
+ XYZ oldmid2;
+
+ tempmult=multiplier;
+ multiplier/=10;
+ for(int l=0;l<10;l++){
+ if(owner[i]==-1&&(velocity[i].x||velocity[i].y||velocity[i].z)&&physics[i]){
+ //move
+ position[i]+=velocity[i]*multiplier;
+ tippoint[i]+=tipvelocity[i]*multiplier;
+
+ //Length constrain
+ midp=(position[i]*mass[i]+tippoint[i]*tipmass[i])/(mass[i]+tipmass[i]);
+ vel=tippoint[i]-midp;
+ Normalise(&vel);
+ newpoint1=midp-vel*length[i]*(tipmass[i]/(mass[i]+tipmass[i]));
+ newpoint2=midp+vel*length[i]*(mass[i]/(mass[i]+tipmass[i]));
+ if(!freeze){
+ if(freetime[i]>.04)velocity[i]=velocity[i]+(newpoint1-position[i])/multiplier;
+ if(freetime[i]>.04)tipvelocity[i]=tipvelocity[i]+(newpoint2-tippoint[i])/multiplier;
+ }
+ position[i]=newpoint1;
+ tippoint[i]=newpoint2;
+
+
+ //Object collisions
+ whichpatchx=(position[i].x)/(terrain.size/subdivision*terrain.scale*terraindetail);
+ whichpatchz=(position[i].z)/(terrain.size/subdivision*terrain.scale*terraindetail);
+ if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
+ if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
+ for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
+ k=terrain.patchobjects[whichpatchx][whichpatchz][j];
+
+ if(firstfree[i]){
+ if(type[i]!=staff){
+ start=position[i]-(tippoint[i]-position[i])/5;
+ end=tippoint[i]+(tippoint[i]-position[i])/30;
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ XYZ diff;
+ diff=(colpoint-tippoint[i]);
+ Normalise(&diff);
+ hitsomething[i]=1;
+
+ position[i]+=(colpoint-tippoint[i])+diff*.05;
+ tippoint[i]=colpoint+diff*.05;
+ oldposition[i]=position[i];
+ oldtippoint[i]=tippoint[i];
+ }
+ }
+ if(type[i]==staff){
+ start=tippoint[i]-(position[i]-tippoint[i])/5;
+ end=position[i]+(position[i]-tippoint[i])/30;
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ XYZ diff;
+ diff=(colpoint-position[i]);
+ Normalise(&diff);
+ hitsomething[i]=1;
+
+ tippoint[i]+=(colpoint-position[i])+diff*.05;
+ position[i]=colpoint+diff*.05;
+ oldtippoint[i]=tippoint[i];
+ oldposition[i]=tippoint[i];
+ }
+ }
+ }
+
+ start=oldposition[i];
+ end=position[i];
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ hitsomething[i]=1;
+ position[i]=colpoint;
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ ReflectVector(&velocity[i],&terrainnormal);
+ position[i]+=terrainnormal*.002;
+
+ bounceness=terrainnormal*findLength(&velocity[i])*(abs(normaldotproduct(velocity[i],terrainnormal)));
+ if(findLengthfast(&velocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(velocity[i],terrainnormal));
+ velocity[i]-=bounceness;
+ if(1-friction*frictionness>0)velocity[i]*=1-friction*frictionness;
+ else velocity[i]=0;
+ velocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ //int whichsound=clank1sound+abs(Random()%4);
+ int whichsound;
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+ start=oldtippoint[i];
+ end=tippoint[i];
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ hitsomething[i]=1;
+ tippoint[i]=colpoint;
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ ReflectVector(&tipvelocity[i],&terrainnormal);
+ tippoint[i]+=terrainnormal*.002;
+
+ bounceness=terrainnormal*findLength(&tipvelocity[i])*(abs(normaldotproduct(tipvelocity[i],terrainnormal)));
+ if(findLengthfast(&tipvelocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(tipvelocity[i],terrainnormal));
+ tipvelocity[i]-=bounceness;
+ if(1-friction*frictionness>0)tipvelocity[i]*=1-friction*frictionness;
+ else tipvelocity[i]=0;
+ tipvelocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ //int whichsound=clank1sound+abs(Random()%4);
+ int whichsound;
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);gLoc[0]=position[i].x;
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+ if((objects.type[k]!=boxtype&&objects.type[k]!=platformtype&&objects.type[k]!=walltype&&objects.type[k]!=weirdtype)||objects.rotation2[k]!=0)
+ for(m=0;m<2;m++){
+ mid=(position[i]*(21+(float)m*10)+tippoint[i]*(19-(float)m*10))/40;
+ oldmid2=mid;
+ oldmid=(oldposition[i]*(21+(float)m*10)+oldtippoint[i]*(19-(float)m*10))/40;
+
+ start=oldmid;
+ end=mid;
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ hitsomething[i]=1;
+ mid=colpoint;
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ ReflectVector(&velocity[i],&terrainnormal);
+
+ bounceness=terrainnormal*findLength(&velocity[i])*(abs(normaldotproduct(velocity[i],terrainnormal)));
+ if(findLengthfast(&velocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(velocity[i],terrainnormal));
+ velocity[i]-=bounceness;
+ if(1-friction*frictionness>0)velocity[i]*=1-friction*frictionness;
+ else velocity[i]=0;
+ velocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ //int whichsound=clank1sound+abs(Random()%4);
+ int whichsound;
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);gLoc[0]=mid.x;
+ gLoc[1]=mid.y;
+ gLoc[2]=mid.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ position[i]+=(mid-oldmid2)*(20/(1+(float)m*10));
+ }
+
+ mid=(position[i]*(19-(float)m*10)+tippoint[i]*(21+(float)m*10))/40;
+ oldmid2=mid;
+ oldmid=(oldposition[i]*(19-(float)m*10)+oldtippoint[i]*(21+(float)m*10))/40;
+
+ start=oldmid;
+ end=mid;
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ hitsomething[i]=1;
+ mid=colpoint;
+ terrainnormal=DoRotation(objects.model[k].facenormals[whichhit],0,objects.rotation[k],0)*-1;
+ ReflectVector(&tipvelocity[i],&terrainnormal);
+
+ bounceness=terrainnormal*findLength(&tipvelocity[i])*(abs(normaldotproduct(tipvelocity[i],terrainnormal)));
+ if(findLengthfast(&tipvelocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(tipvelocity[i],terrainnormal));
+ tipvelocity[i]-=bounceness;
+ if(1-friction*frictionness>0)tipvelocity[i]*=1-friction*frictionness;
+ else tipvelocity[i]=0;
+ tipvelocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ //int whichsound=clank1sound+abs(Random()%4);
+ int whichsound;
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);gLoc[0]=mid.x;
+ gLoc[1]=mid.y;
+ gLoc[2]=mid.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ tippoint[i]+=(mid-oldmid2)*(20/(1+(float)m*10));
+ }
+ }
+ else
+ {
+ start=position[i];
+ end=tippoint[i];
+ whichhit=objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k]);
+ if(whichhit!=-1){
+ hitsomething[i]=1;
+ closestdistance=-1;
+ closestswordpoint=colpoint;//(position[i]+tippoint[i])/2;
+ point[0]=DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[0]],0,objects.rotation[k],0)+objects.position[k];
+ point[1]=DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[1]],0,objects.rotation[k],0)+objects.position[k];
+ point[2]=DoRotation(objects.model[k].vertex[objects.model[k].Triangles[whichhit].vertex[2]],0,objects.rotation[k],0)+objects.position[k];
+ if(DistancePointLine(&closestswordpoint, &point[0], &point[1], &distance,&colpoint ))
+ if(distance<closestdistance||closestdistance==-1){
+ closestpoint=colpoint;
+ closestdistance=distance;
+ closestline=0;
+ }
+ if(DistancePointLine(&closestswordpoint, &point[1], &point[2], &distance,&colpoint ))
+ if(distance<closestdistance||closestdistance==-1){
+ closestpoint=colpoint;
+ closestdistance=distance;
+ closestline=1;
+ }
+ if(DistancePointLine(&closestswordpoint, &point[2], &point[0], &distance,&colpoint ))
+ if(distance<closestdistance||closestdistance==-1){
+ closestpoint=colpoint;
+ closestdistance=distance;
+ closestline=2;
+ }
+ if(closestdistance!=-1&&isnormal(closestdistance)){
+ if(DistancePointLine(&closestpoint, &position[i], &tippoint[i], &distance,&colpoint )){
+ closestswordpoint=colpoint;
+ velocity[i]+=(closestpoint-closestswordpoint);
+ tipvelocity[i]+=(closestpoint-closestswordpoint);
+ position[i]+=(closestpoint-closestswordpoint);
+ tippoint[i]+=(closestpoint-closestswordpoint);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ //Terrain collisions
+ whichhit=terrain.lineTerrain(oldposition[i],position[i],&colpoint);
+ if(whichhit!=-1||position[i].y<terrain.getHeight(position[i].x,position[i].z)){
+ hitsomething[i]=1;
+ if(whichhit!=-1)position[i]=colpoint*terrain.scale;
+ else position[i].y=terrain.getHeight(position[i].x,position[i].z);
+
+ terrainnormal=terrain.getNormal(position[i].x,position[i].z);
+ ReflectVector(&velocity[i],&terrainnormal);
+ position[i]+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&velocity[i])*(abs(normaldotproduct(velocity[i],terrainnormal)));
+ if(findLengthfast(&velocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(velocity[i],terrainnormal));
+ velocity[i]-=bounceness;
+ if(1-friction*frictionness>0)velocity[i]*=1-friction*frictionness;
+ else velocity[i]=0;
+ if(terrain.getOpacity(position[i].x,position[i].z)<.2)velocity[i]+=bounceness*elasticity*.3;
+ else velocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(position[i].x,position[i].z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(position[i].x,position[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+
+ if(terrain.getOpacity(position[i].x,position[i].z)<.2){
+ XYZ terrainlight;
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ if(environment==snowyenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x,terrainlight.y,terrainlight.z, .5, .7);
+ }
+ else if(environment==grassyenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x*90/255,terrainlight.y*70/255,terrainlight.z*8/255, .5, .5);
+ }
+ else if(environment==desertenvironment){
+ if(findDistancefast(&position[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, position[i],velocity[i], terrainlight.x*190/255,terrainlight.y*170/255,terrainlight.z*108/255, .5, .7);
+ }
+ }
+ }
+ }
+ whichhit=terrain.lineTerrain(oldtippoint[i],tippoint[i],&colpoint);
+ if(whichhit!=-1||tippoint[i].y<terrain.getHeight(tippoint[i].x,tippoint[i].z)){
+ if(whichhit!=-1)tippoint[i]=colpoint*terrain.scale;
+ else tippoint[i].y=terrain.getHeight(tippoint[i].x,tippoint[i].z);
+
+ terrainnormal=terrain.getNormal(tippoint[i].x,tippoint[i].z);
+ ReflectVector(&tipvelocity[i],&terrainnormal);
+ tippoint[i]+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&tipvelocity[i])*(abs(normaldotproduct(tipvelocity[i],terrainnormal)));
+ if(findLengthfast(&tipvelocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(tipvelocity[i],terrainnormal));
+ tipvelocity[i]-=bounceness;
+ if(1-friction*frictionness>0)tipvelocity[i]*=1-friction*frictionness;
+ else tipvelocity[i]=0;
+ if(terrain.getOpacity(tippoint[i].x,tippoint[i].z)<.2)tipvelocity[i]+=bounceness*elasticity*.3;
+ else tipvelocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(tippoint[i].x,tippoint[i].z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=tippoint[i].x;
+ gLoc[1]=tippoint[i].y;
+ gLoc[2]=tippoint[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(tippoint[i].x,tippoint[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+
+ if(terrain.getOpacity(tippoint[i].x,tippoint[i].z)<.2){
+ XYZ terrainlight;
+ terrainlight=terrain.getLighting(tippoint[i].x,tippoint[i].z);
+ if(environment==snowyenvironment){
+ if(findDistancefast(&tippoint[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, tippoint[i],tipvelocity[i], terrainlight.x,terrainlight.y,terrainlight.z, .5, .7);
+ }
+ else if(environment==grassyenvironment){
+ if(findDistancefast(&tippoint[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, tippoint[i],tipvelocity[i], terrainlight.x*90/255,terrainlight.y*70/255,terrainlight.z*8/255, .5, .5);
+ }
+ else if(environment==desertenvironment){
+ if(findDistancefast(&tippoint[i],&viewer)<viewdistance*viewdistance/4)sprites.MakeSprite(cloudsprite, tippoint[i],tipvelocity[i], terrainlight.x*190/255,terrainlight.y*170/255,terrainlight.z*108/255, .5, .7);
+ }
+ }
+ }
+ }
+
+ //Edges
+ mid=position[i]+tippoint[i];
+ mid/=2;
+ mid+=(position[i]-mid)/20;
+ oldmid=mid;
+ if(mid.y<terrain.getHeight(mid.x,mid.z)){
+ hitsomething[i]=1;
+ mid.y=terrain.getHeight(mid.x,mid.z);
+
+ terrainnormal=terrain.getNormal(mid.x,mid.z);
+ ReflectVector(&velocity[i],&terrainnormal);
+ //mid+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&velocity[i])*(abs(normaldotproduct(velocity[i],terrainnormal)));
+ if(findLengthfast(&velocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(velocity[i],terrainnormal));
+ velocity[i]-=bounceness;
+ if(1-friction*frictionness>0)velocity[i]*=1-friction*frictionness;
+ else velocity[i]=0;
+ if(terrain.getOpacity(mid.x,mid.z)<.2)velocity[i]+=bounceness*elasticity*.3;
+ else velocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(mid.x,mid.z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=mid.x;
+ gLoc[1]=mid.y;
+ gLoc[2]=mid.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(position[i].x,position[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ position[i]+=(mid-oldmid)*20;
+ }
+
+ mid=position[i]+tippoint[i];
+ mid/=2;
+ mid+=(tippoint[i]-mid)/20;
+ oldmid=mid;
+ if(mid.y<terrain.getHeight(mid.x,mid.z)){
+ hitsomething[i]=1;
+ mid.y=terrain.getHeight(mid.x,mid.z);
+
+ terrainnormal=terrain.getNormal(mid.x,mid.z);
+ ReflectVector(&tipvelocity[i],&terrainnormal);
+ //mid+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&tipvelocity[i])*(abs(normaldotproduct(tipvelocity[i],terrainnormal)));
+ if(findLengthfast(&tipvelocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(tipvelocity[i],terrainnormal));
+ tipvelocity[i]-=bounceness;
+ if(1-friction*frictionness>0)tipvelocity[i]*=1-friction*frictionness;
+ else tipvelocity[i]=0;
+ if(terrain.getOpacity(mid.x,mid.z)<.2)tipvelocity[i]+=bounceness*elasticity*.3;
+ else tipvelocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(mid.x,mid.z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=mid.x;
+ gLoc[1]=mid.y;
+ gLoc[2]=mid.z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(position[i].x,position[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ tippoint[i]+=(mid-oldmid)*20;
+ }
+ /*XYZ mid;
+ mid=position[i]+tippoint[i];
+ mid/=2;
+ if(position[i].y<terrain.getHeightExtrude(mid.x,mid.z,position[i].x,position[i].z)){
+ hitsomething[i]=1;
+ position[i].y=terrain.getHeightExtrude(mid.x,mid.z,position[i].x,position[i].z);
+
+ terrainnormal=terrain.getNormal(mid.x,mid.z);
+ ReflectVector(&velocity[i],&terrainnormal);
+ position[i]+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&velocity[i])*(abs(normaldotproduct(velocity[i],terrainnormal)));
+ if(findLengthfast(&velocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(velocity[i],terrainnormal));
+ velocity[i]-=bounceness;
+ if(1-friction*frictionness>0)velocity[i]*=1-friction*frictionness;
+ else velocity[i]=0;
+ if(terrain.getOpacity(mid.x,mid.z)<.2)velocity[i]+=bounceness*elasticity*.3;
+ else velocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(mid.x,mid.z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=position[i].x;
+ gLoc[1]=position[i].y;
+ gLoc[2]=position[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(position[i].x,position[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }
+
+ if(tippoint[i].y<terrain.getHeightExtrude(mid.x,mid.z,tippoint[i].x,tippoint[i].z)){
+ hitsomething[i]=1;
+ tippoint[i].y=terrain.getHeightExtrude(mid.x,mid.z,tippoint[i].x,tippoint[i].z);
+
+ terrainnormal=terrain.getNormal(mid.x,mid.z);
+ ReflectVector(&tipvelocity[i],&terrainnormal);
+ tippoint[i]+=terrainnormal*.002;
+ bounceness=terrainnormal*findLength(&tipvelocity[i])*(abs(normaldotproduct(tipvelocity[i],terrainnormal)));
+ if(findLengthfast(&tipvelocity[i])<findLengthfast(&bounceness))bounceness=0;
+ frictionness=abs(normaldotproduct(tipvelocity[i],terrainnormal));
+ tipvelocity[i]-=bounceness;
+ if(1-friction*frictionness>0)tipvelocity[i]*=1-friction*frictionness;
+ else tipvelocity[i]=0;
+ if(terrain.getOpacity(mid.x,mid.z)<.2)tipvelocity[i]+=bounceness*elasticity*.3;
+ else tipvelocity[i]+=bounceness*elasticity;
+
+ if(findLengthfast(&bounceness)>1){
+ float gLoc[3];
+ float vel[3];
+ int whichsound;
+ if(terrain.getOpacity(mid.x,mid.z)>.2){
+ if(type[i]==staff)whichsound=footstepsound3+abs(Random()%2);
+ if(type[i]!=staff)whichsound=clank1sound+abs(Random()%4);
+ }
+ else whichsound=footstepsound+abs(Random()%2);
+ gLoc[0]=tippoint[i].x;
+ gLoc[1]=tippoint[i].y;
+ gLoc[2]=tippoint[i].z;
+ vel[0]=0;
+ vel[1]=0;
+ vel[2]=0;
+ PlaySoundEx( whichsound, samp[whichsound], NULL, TRUE);
+ FSOUND_3D_SetAttributes(channels[whichsound], gLoc, vel);
+ if(terrain.getOpacity(tippoint[i].x,tippoint[i].z)>.2)FSOUND_SetVolume(channels[whichsound], 128*findLengthfast(&bounceness));
+ else FSOUND_SetVolume(channels[whichsound], 32*findLengthfast(&bounceness));
+ FSOUND_SetPaused(channels[whichsound], FALSE);
+ }
+ }*/
+
+ //Fix terrain edge collision
+ /*start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ if(whichhit!=-1){
+ XYZ tippoi,posit;
+ tippoi=tippoint[i];
+ posit=position[i];
+
+
+ while(whichhit!=-1){
+ position[i].y+=.1;
+ tippoint[i].y+=.1;
+ velocity[i].y+=.1;
+ tipvelocity[i].y+=.1;
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ if(whichhit!=-1)
+ closestpoint=colpoint*terrain.scale;
+ }
+ position[i].y-=.1;
+ tippoint[i].y-=.1;
+ velocity[i].y-=.1;
+ tipvelocity[i].y-=.1;
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ while(whichhit!=-1){
+ position[i].y+=.01;
+ tippoint[i].y+=.01;
+ velocity[i].y+=.01;
+ tipvelocity[i].y+=.01;
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ if(whichhit!=-1)
+ closestpoint=colpoint*terrain.scale;
+ }
+ }*/
+ /*if(whichhit!=-1){
+ whichhit=terrain.lineTerrain(end,start,&closestswordpoint);
+ if(whichhit!=-1){
+ colpoint=(closestswordpoint*terrain.scale+colpoint*terrain.scale)/2;
+ proportion=findDistance(&tippoint[i],&colpoint)/findDistance(&position[i],&tippoint[i]);
+ if(proportion<=1){
+ while(whichhit!=-1){
+ position[i].y+=.1*proportion;
+ tippoint[i].y+=.1*(1-proportion);
+ velocity[i].y+=.1*proportion;
+ tipvelocity[i].y+=.1*(1-proportion);
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ }
+ position[i].y-=.1*proportion;
+ tippoint[i].y-=.1*(1-proportion);
+ velocity[i].y-=.1*proportion;
+ tipvelocity[i].y-=.1*(1-proportion);
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ while(whichhit!=-1){
+ position[i].y+=.01*proportion;
+ tippoint[i].y+=.01*(1-proportion);
+ velocity[i].y+=.01*proportion;
+ tipvelocity[i].y+=.01*(1-proportion);
+ start=position[i];
+ end=tippoint[i];
+ whichhit=terrain.lineTerrain(start,end,&colpoint);
+ }
+ }
+ }
+ }
+ */
+ //Gravity
+ velocity[i].y+=gravity*multiplier;
+ tipvelocity[i].y+=gravity*multiplier;
+ //position[i].y+=gravity*multiplier*multiplier;
+ //tippoint[i].y+=gravity*multiplier*multiplier;
+
+ //Rotation
+ XYZ temppoint1,temppoint2,tempforward;
+ float distance;
+
+ temppoint1=position[i];
+ temppoint2=tippoint[i];
+ distance=findDistance(&temppoint1,&temppoint2);
+ rotation2[i]=asin((temppoint1.y-temppoint2.y)/distance);
+ rotation2[i]*=360/6.28;
+ temppoint1.y=0;
+ temppoint2.y=0;
+ rotation1[i]=acos((temppoint1.z-temppoint2.z)/findDistance(&temppoint1,&temppoint2));
+ rotation1[i]*=360/6.28;
+ rotation3[i]=0;
+ smallrotation[i]=90;
+ smallrotation2[i]=0;
+ bigtilt[i]=0;
+ bigtilt2[i]=0;
+ bigrotation[i]=0;
+ if(temppoint1.x>temppoint2.x)rotation1[i]=360-rotation1[i];
+
+ //Stop moving
+ if(findLengthfast(&velocity[i])<.3&&findLengthfast(&tipvelocity[i])<.3&&hitsomething[i]){
+ freetime[i]+=multiplier;
+ }
+
+ //velocity[i]=(position[i]-oldposition[i])/multiplier;
+ //tipvelocity[i]==(tippoint[i-+oldtippoint[i])/multiplier;
+ if(freetime[i]>.4){
+ velocity[i]=0;
+ tipvelocity[i]=0;
+ }
+ firstfree[i]=0;
+ }
+ }
+ multiplier=tempmult;
+ if(blooddrip[i]&&bloody[i]){
+ blooddripdelay[i]-=blooddrip[i]*multiplier/2;
+ blooddrip[i]-=multiplier;
+ if(blooddrip[i]<0)blooddrip[i]=0;
+ if(blooddrip[i]>5)blooddrip[i]=5;
+ if(blooddripdelay[i]<0&&bloodtoggle){
+ blooddripdelay[i]=1;
+ XYZ bloodvel;
+ XYZ bloodloc;
+ bloodloc=position[i]+(tippoint[i]-position[i])*.7;
+ bloodloc.y-=.05;
+ if(bloodtoggle){
+ bloodvel=0;
+ sprites.MakeSprite(bloodsprite, bloodloc,bloodvel, 1,1,1, .03, 1);
+ }
+ }
+ }
+ if(onfire[i]){
+ flamedelay[i]-=multiplier;
+ if(onfire[i]&&flamedelay[i]<=0){
+ flamedelay[i]=.020;
+ flamedelay[i]-=multiplier;
+ normalrot=0;
+ if(owner[i]!=-1){
+ normalrot=player[owner[i]].velocity;
+ }
+ normalrot.y+=1;
+ if(owner[i]!=-1){
+ if(player[owner[i]].onterrain){
+ normalrot.y=1;
+ }
+ }
+ sprites.MakeSprite(weaponflamesprite, position[i]+tippoint[i]*(((float)abs(Random()%100))/600+.05),normalrot, 1,1,1, (.6+(float)abs(Random()%100)/200-.25)*1/3, 1);
+ sprites.speed[sprites.numsprites-1]=4;
+ sprites.alivetime[sprites.numsprites-1]=.3;
+ }
+ }
+
+ if(!onfire[i]&&owner[i]==-1&&type[i]!=staff){
+ flamedelay[i]-=multiplier;
+ if(flamedelay[i]<=0){
+ flamedelay[i]=.020;
+ flamedelay[i]-=multiplier;
+ normalrot=0;
+ if(Random()%50==0&&findDistancefast(&position[i],&viewer)>80){
+ XYZ shinepoint;
+ shinepoint=position[i]+(tippoint[i]-position[i])*(((float)abs(Random()%100))/100);
+ sprites.MakeSprite(weaponshinesprite, shinepoint,normalrot, 1,1,1, (.1+(float)abs(Random()%100)/200-.25)*1/3*fast_sqrt(findDistance(&shinepoint,&viewer)), 1);
+ sprites.speed[sprites.numsprites-1]=4;
+ sprites.alivetime[sprites.numsprites-1]=.3;
+ }
+ }
+ }
+ }
+}
+
+int Weapons::Draw()
+{
+ static int i,j;
+ static XYZ terrainlight;
+ static GLfloat M[16];
+ static bool draw;
+ glAlphaFunc(GL_GREATER, 0.9);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+ glDepthMask(1);
+ for(i=0;i<numweapons;i++)
+ {
+ if((frustum.SphereInFrustum(position[i].x,position[i].y,position[i].z,1)&&findDistancefast(&viewer,&position[i])<viewdistance*viewdistance))
+ {
+ draw=0;
+ if(owner[i]==-1)
+ {
+ draw=1;
+ if(velocity[i].x&&!physics[i])drawhowmany[i]=10;
+ else drawhowmany[i]=1;
+ }
+ if(owner[i]!=-1)
+ {
+ if(player[owner[i]].occluded<25)
+ if((frustum.SphereInFrustum(player[owner[i]].coords.x,player[owner[i]].coords.y+player[owner[i]].scale*3,player[owner[i]].coords.z,player[owner[i]].scale*8)&&findDistancefast(&viewer,&player[owner[i]].coords)<viewdistance*viewdistance)||player[owner[i]].skeleton.free==3)
+ draw=1;
+ if((player[owner[i]].targetanimation==knifeslashstartanim||player[owner[i]].targetanimation==swordsneakattackanim||(player[owner[i]].currentanimation==staffhitanim&&player[owner[i]].currentframe>1)||(player[owner[i]].currentanimation==staffhitreversedanim&&player[owner[i]].currentframe>1)||(player[owner[i]].currentanimation==staffspinhitanim&&player[owner[i]].currentframe>1)||(player[owner[i]].currentanimation==staffspinhitreversedanim&&player[owner[i]].currentframe>1)||(player[owner[i]].currentanimation==staffgroundsmashanim&&player[owner[i]].currentframe>1)||(player[owner[i]].targetanimation==swordslashanim&&player[owner[i]].targetframe<7)||player[owner[i]].targetanimation==crouchstabanim||player[owner[i]].targetanimation==swordslashreversalanim||player[owner[i]].targetanimation==swordslashreversedanim||player[owner[i]].targetanimation==knifefollowanim||player[owner[i]].targetanimation==swordgroundstabanim||player[owner[i]].targetanimation==knifethrowanim)&&player[owner[i]].targetanimation==lastdrawnanim[i]&&!player[owner[i]].skeleton.free)
+ {
+ drawhowmany[i]=10;
+ }
+ else drawhowmany[i]=1;
+ if(player[owner[i]].targetanimation==swordgroundstabanim)
+ {
+ lastdrawnrotation1[i]=rotation1[i];
+ lastdrawnrotation2[i]=rotation2[i];
+ lastdrawnrotation3[i]=rotation3[i];
+ lastdrawnbigrotation[i]=bigrotation[i];
+ lastdrawnbigtilt[i]=bigtilt[i];
+ lastdrawnbigtilt2[i]=bigtilt2[i];
+ lastdrawnsmallrotation[i]=smallrotation[i];
+ lastdrawnsmallrotation2[i]=smallrotation2[i];
+ }
+ }
+ if(draw)
+ {
+ terrainlight=terrain.getLighting(position[i].x,position[i].z);
+ if(drawhowmany[i]>0)
+ {
+ glAlphaFunc(GL_GREATER, 0.01);
+ }
+ for(j=drawhowmany[i];j>0;j--)
+ {
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glColor4f(terrainlight.x,terrainlight.y,terrainlight.z,j/drawhowmany[i]);
+ if(owner[i]!=-1)glTranslatef(position[i].x*(((float)(j))/drawhowmany[i])+lastdrawnposition[i].x*(1-((float)(j))/drawhowmany[i]),position[i].y*(((float)(j))/drawhowmany[i])-.02+lastdrawnposition[i].y*(1-((float)(j))/drawhowmany[i]),position[i].z*(((float)(j))/drawhowmany[i])+lastdrawnposition[i].z*(1-((float)(j))/drawhowmany[i]));
+ if(owner[i]==-1)glTranslatef(position[i].x*(((float)(j))/drawhowmany[i])+lastdrawnposition[i].x*(1-((float)(j))/drawhowmany[i]),position[i].y*(((float)(j))/drawhowmany[i])+lastdrawnposition[i].y*(1-((float)(j))/drawhowmany[i]),position[i].z*(((float)(j))/drawhowmany[i])+lastdrawnposition[i].z*(1-((float)(j))/drawhowmany[i]));
+ //glTranslatef(position[i].x,position[i].y-.02,position[i].z);
+ glRotatef(bigrotation[i]*(((float)(j))/drawhowmany[i])+lastdrawnbigrotation[i]*(1-((float)(j))/drawhowmany[i]),0,1,0);
+ glRotatef(bigtilt2[i]*(((float)(j))/drawhowmany[i])+lastdrawnbigtilt2[i]*(1-((float)(j))/drawhowmany[i]),1,0,0);
+ glRotatef(bigtilt[i]*(((float)(j))/drawhowmany[i])+lastdrawnbigtilt[i]*(1-((float)(j))/drawhowmany[i]),0,0,1);
+ glRotatef(-rotation1[i]*(((float)(j))/drawhowmany[i])-lastdrawnrotation1[i]*(1-((float)(j))/drawhowmany[i])+90,0,1,0);
+ glRotatef(-rotation2[i]*(((float)(j))/drawhowmany[i])-lastdrawnrotation2[i]*(1-((float)(j))/drawhowmany[i])+90,0,0,1);
+ glRotatef(-rotation3[i]*(((float)(j))/drawhowmany[i])-lastdrawnrotation3[i]*(1-((float)(j))/drawhowmany[i]),0,1,0);
+ glRotatef(smallrotation[i]*(((float)(j))/drawhowmany[i])+lastdrawnsmallrotation[i]*(1-((float)(j))/drawhowmany[i]),1,0,0);
+ glRotatef(smallrotation2[i]*(((float)(j))/drawhowmany[i])+lastdrawnsmallrotation2[i]*(1-((float)(j))/drawhowmany[i]),0,1,0);
+
+ if(owner[i]!=-1)
+ {
+ if(player[owner[i]].targetanimation==staffhitanim||player[owner[i]].currentanimation==staffhitanim||player[owner[i]].targetanimation==staffhitreversedanim||player[owner[i]].currentanimation==staffhitreversedanim)
+ {
+ glTranslatef(0,0,-.3);
+ }
+ if(player[owner[i]].targetanimation==staffgroundsmashanim||player[owner[i]].currentanimation==staffgroundsmashanim||player[owner[i]].targetanimation==staffspinhitreversedanim||player[owner[i]].currentanimation==staffspinhitreversedanim||player[owner[i]].targetanimation==staffspinhitanim||player[owner[i]].currentanimation==staffspinhitanim)
+ {
+ glTranslatef(0,0,-.1);
+ }
+ }
+ /*if(type[i]==knife){
+ if(owner[i]==-1){
+ if(!physics[i]&&findDistance(&position[i],&oldposition[i])*5>1)glScalef(1,1,findDistance(&position[i],&oldposition[i])*5);
+ }
+ }*/
+
+ if(type[i]==knife)
+ {
+ glEnable(GL_LIGHTING);
+ if(!bloody[i]||!bloodtoggle)throwingknifemodel.drawdifftex(knifetextureptr);
+ if(bloodtoggle)
+ {
+ if(bloody[i]==1)throwingknifemodel.drawdifftex(lightbloodknifetextureptr);
+ if(bloody[i]==2)throwingknifemodel.drawdifftex(bloodknifetextureptr);
+ }
+ }
+ if(type[i]==sword)
+ {
+ glEnable(GL_LIGHTING);
+ if(!bloody[i]||!bloodtoggle)swordmodel.drawdifftex(swordtextureptr);
+ if(bloodtoggle)
+ {
+ if(bloody[i]==1)swordmodel.drawdifftex(lightbloodswordtextureptr);
+ if(bloody[i]==2)swordmodel.drawdifftex(bloodswordtextureptr);
+ }
+ }
+ if(type[i]==staff)
+ {
+ glEnable(GL_LIGHTING);
+ staffmodel.drawdifftex(stafftextureptr);
+ }
+
+ glPopMatrix();
+ }
+
+ lastdrawnposition[i]=position[i];
+ lastdrawntippoint[i]=tippoint[i];
+ lastdrawnrotation1[i]=rotation1[i];
+ lastdrawnrotation2[i]=rotation2[i];
+ lastdrawnrotation3[i]=rotation3[i];
+ lastdrawnbigrotation[i]=bigrotation[i];
+ lastdrawnbigtilt[i]=bigtilt[i];
+ lastdrawnbigtilt2[i]=bigtilt2[i];
+ lastdrawnsmallrotation[i]=smallrotation[i];
+ lastdrawnsmallrotation2[i]=smallrotation2[i];
+ if(owner[i]!=-1)lastdrawnanim[i]=player[owner[i]].currentanimation;
+ }
+ if(owner[i]!=-1)
+ {
+ glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef(position[i].x,position[i].y-.02,position[i].z);
+ glRotatef(bigrotation[i],0,1,0);
+ glRotatef(bigtilt2[i],1,0,0);
+ glRotatef(bigtilt[i],0,0,1);
+ glRotatef(-rotation1[i]+90,0,1,0);
+ glRotatef(-rotation2[i]+90,0,0,1);
+ glRotatef(-rotation3[i],0,1,0);
+ glRotatef(smallrotation[i],1,0,0);
+ glRotatef(smallrotation2[i],0,1,0);
+ glTranslatef(0,0,length[i]);
+ glGetFloatv(GL_MODELVIEW_MATRIX,M);
+ tippoint[i].x=M[12];
+ tippoint[i].y=M[13];
+ tippoint[i].z=M[14];
+ glPopMatrix();
+ }
+ /*XYZ shinepoint;
+ XYZ nothingpoint;
+ nothingpoint=0;
+ shinepoint=position[i];
+ sprites.MakeSprite(weaponshinesprite, shinepoint,nothingpoint, 1,1,1,multiplier*2, 1);
+ sprites.speed[sprites.numsprites-1]=4;
+ sprites.alivetime[sprites.numsprites-1]=.3;
+ shinepoint=tippoint[i];
+ sprites.MakeSprite(weaponshinesprite, shinepoint,nothingpoint, 1,1,1,multiplier*2, 1);
+ sprites.speed[sprites.numsprites-1]=4;
+ sprites.alivetime[sprites.numsprites-1]=.3;*/
+ }
+ }
+ return 0;
+}
+
+Weapons::Weapons()
+{
+ rotation1.resize(max_weaponinstances);
+ rotation2.resize(max_weaponinstances);
+ rotation3.resize(max_weaponinstances);
+ bigrotation.resize(max_weaponinstances);
+ bigtilt.resize(max_weaponinstances);
+ bigtilt2.resize(max_weaponinstances);
+ smallrotation.resize(max_weaponinstances);
+ smallrotation2.resize(max_weaponinstances);
+ damage.resize(max_weaponinstances);
+
+ numweapons = 0;
+ tippoint.resize(max_weaponinstances);
+ oldtippoint.resize(max_weaponinstances);
+ position.resize(max_weaponinstances);
+ lastmult.resize(max_weaponinstances);
+ oldposition.resize(max_weaponinstances);
+ velocity.resize(max_weaponinstances);
+ tipvelocity.resize(max_weaponinstances);
+ type.resize(max_weaponinstances);
+ oldowner.resize(max_weaponinstances);
+ owner.resize(max_weaponinstances);
+ bloody.resize(max_weaponinstances);
+ blooddrip.resize(max_weaponinstances);
+ blooddripdelay.resize(max_weaponinstances);
+ onfire.resize(max_weaponinstances);
+ flamedelay.resize(max_weaponinstances);
+ missed.resize(max_weaponinstances);
+ mass.resize(max_weaponinstances);
+ tipmass.resize(max_weaponinstances);
+ length.resize(max_weaponinstances);
+ freetime.resize(max_weaponinstances);
+ firstfree.resize(max_weaponinstances);
+ physics.resize(max_weaponinstances);
+ drawhowmany.resize(max_weaponinstances);
+ hitsomething.resize(max_weaponinstances);
+
+ lastdrawnposition.resize(max_weaponinstances);
+ lastdrawntippoint.resize(max_weaponinstances);
+ lastdrawnrotation1.resize(max_weaponinstances);
+ lastdrawnrotation2.resize(max_weaponinstances);
+ lastdrawnrotation3.resize(max_weaponinstances);
+ lastdrawnbigrotation.resize(max_weaponinstances);
+ lastdrawnbigtilt.resize(max_weaponinstances);
+ lastdrawnbigtilt2.resize(max_weaponinstances);
+ lastdrawnsmallrotation.resize(max_weaponinstances);
+ lastdrawnsmallrotation2.resize(max_weaponinstances);
+ lastdrawnanim.resize(max_weaponinstances);
+
+ // Model throwingknifemodel;
+ knifetextureptr = 0;
+ lightbloodknifetextureptr = 0;
+ bloodknifetextureptr = 0;
+
+ // Model swordmodel;
+ swordtextureptr = 0;
+ lightbloodswordtextureptr = 0;
+ bloodswordtextureptr = 0;
+
+ // Model staffmodel;
+ stafftextureptr = 0;
+}
+
+Weapons::~Weapons()
+{
+ if (stafftextureptr) glDeleteTextures( 1, (const unsigned long *)&stafftextureptr );
+ if (knifetextureptr) glDeleteTextures( 1, (const unsigned long *)&knifetextureptr );
+ if (lightbloodknifetextureptr) glDeleteTextures( 1, (const unsigned long *)&lightbloodknifetextureptr );
+ if (bloodknifetextureptr) glDeleteTextures( 1, (const unsigned long *)&bloodknifetextureptr );
+ if (swordtextureptr) glDeleteTextures( 1, (const unsigned long *)&swordtextureptr );
+ if (lightbloodswordtextureptr) glDeleteTextures( 1, (const unsigned long *)&lightbloodswordtextureptr );
+ if (bloodswordtextureptr) glDeleteTextures( 1, (const unsigned long *)&bloodswordtextureptr );
+}
--- /dev/null
+#ifndef _WEAPONS_H_
+#define _WEAPONS_H_
+
+/**> HEADER FILES <**/
+
+#include "gl.h"
+#include "Quaternions.h"
+#include "fmod.h"
+#include "skeleton.h"
+#include "models.h"
+#include "Constants.h"
+#include "Terrain.h"
+#include "Sprites.h"
+#include "Person.h"
+#include <cmath>
+
+#define max_weapons 30
+#define max_weaponinstances 20
+
+#define knife 1
+#define sword 2
+#define staff 3
+
+class Weapons
+{
+public:
+
+ std::vector<float> rotation1,rotation2,rotation3;
+ std::vector<float> bigrotation;
+ std::vector<float> bigtilt;
+ std::vector<float> bigtilt2;
+ std::vector<float> smallrotation;
+ std::vector<float> smallrotation2;
+
+ int numweapons;
+ std::vector<float> damage;
+ std::vector<XYZ> tippoint;
+ std::vector<XYZ> oldtippoint;
+ std::vector<XYZ> position;
+ std::vector<float> lastmult;
+ std::vector<XYZ> oldposition;
+ std::vector<XYZ> velocity;
+ std::vector<XYZ> tipvelocity;
+ std::vector<int> type;
+ std::vector<int> oldowner;
+ std::vector<int> owner;
+ std::vector<int> bloody;
+ std::vector<float> blooddrip;
+ std::vector<float> blooddripdelay;
+ std::vector<bool> onfire;
+ std::vector<float> flamedelay;
+ std::vector<bool> missed;
+ std::vector<float> mass;
+ std::vector<float> tipmass;
+ std::vector<float> length;
+ std::vector<float> freetime;
+ std::vector<bool> firstfree;
+ std::vector<bool> physics;
+ std::vector<float> drawhowmany;
+ std::vector<bool> hitsomething;
+
+ std::vector<XYZ> lastdrawnposition;
+ std::vector<XYZ> lastdrawntippoint;
+ std::vector<float> lastdrawnrotation1,lastdrawnrotation2,lastdrawnrotation3;
+ std::vector<float> lastdrawnbigrotation;
+ std::vector<float> lastdrawnbigtilt;
+ std::vector<float> lastdrawnbigtilt2;
+ std::vector<float> lastdrawnsmallrotation;
+ std::vector<float> lastdrawnsmallrotation2;
+ std::vector<int> lastdrawnanim;
+
+ Model throwingknifemodel;
+ GLuint knifetextureptr;
+ GLuint lightbloodknifetextureptr;
+ GLuint bloodknifetextureptr;
+
+ Model swordmodel;
+ GLuint swordtextureptr;
+ GLuint lightbloodswordtextureptr;
+ GLuint bloodswordtextureptr;
+
+ Model staffmodel;
+ GLuint stafftextureptr;
+
+ int Draw();
+ void DoStuff();
+
+ Weapons();
+
+ ~Weapons();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "WinDefs.h"
+#include <windows.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+
+
+class AppTime
+{
+public:
+ AppTime()
+ {
+ counterRate = 1;
+ baseCounter = 0;
+ QueryPerformanceFrequency( (LARGE_INTEGER*)&counterRate);
+ QueryPerformanceCounter( (LARGE_INTEGER*)&baseCounter);
+ }
+ __int64 counterRate; // LARGE_INTEGER type has no math functions so use int64
+ __int64 baseCounter;
+};
+static AppTime g_appTime;
+
+
+
+void CopyCStringToPascal( const char* src, unsigned char dst[256])
+{
+ int len = strlen( src);
+ dst[ 0] = len;
+ memcpy( dst + 1, src, len);
+}
+
+
+void CopyPascalStringToC( const unsigned char* src, char* dst)
+{
+ int len = src[ 0];
+ memcpy( dst, src + 1, len);
+ dst[ len] = 0;
+}
+
+
+AbsoluteTime UpTime()
+{
+ __int64 counter;
+ QueryPerformanceCounter( (LARGE_INTEGER*)&counter);
+
+ counter -= g_appTime.baseCounter;
+
+ AbsoluteTime time;
+ time.lo = (unsigned long)counter;
+ time.hi = (unsigned long)(counter >> 32);
+ return time;
+}
+
+
+Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b)
+{
+ __int64 value = a.hi;
+ value <<= 32;
+ value |= a.lo;
+ __int64 value2 = b.hi;
+ value2 <<= 32;
+ value2 |= b.lo;
+ value -= value2;
+
+ if (value <= 0)
+ return durationImmediate;
+
+ __int64 frac = value % g_appTime.counterRate;
+ value /= g_appTime.counterRate;
+
+ Duration time;
+
+ if (value == 0)
+ {
+ frac *= -1000000;
+ frac /= g_appTime.counterRate;
+ time = (Duration)frac;
+ }
+ else
+ {
+ frac *= 1000;
+ frac /= g_appTime.counterRate;
+ value *= 1000;
+ value += frac;
+ time = (Duration)value;
+ }
+
+ return time;
+}
+
+
+static char g_filename[ 256];
+char* ConvertFileName( const char* orgfilename)
+{
+ // translate filename into proper path name
+ if (orgfilename[ 0] == ':')
+ orgfilename++;
+ strcpy( g_filename, orgfilename);
+
+ for (int n = 0; g_filename[ n]; n++)
+ {
+ if (g_filename[ n] == ':')
+ g_filename[ n] = '/';
+ }
+
+ return g_filename;
+}
--- /dev/null
+#ifndef _WINDEFS_H_
+#define _WINDEFS_H_
+#ifdef WIN32
+
+
+#include <stdio.h>
+#include <float.h>
+
+// stuff to make Mac code compatable with Windows
+
+
+// disable warnings about double to float conversions
+#pragma warning(disable:4305)
+#pragma warning(disable:4244)
+
+// disable warnings about boolean to int conversions
+#pragma warning(disable:4800)
+
+// disable warning about unreferenced local variables
+#pragma warning(disable:4101)
+
+typedef bool Boolean;
+
+
+struct Point
+{
+ short v;
+ short h;
+};
+
+typedef signed char SInt8;
+typedef unsigned int UInt32;
+
+
+#include "Random.h"
+
+
+void CopyCStringToPascal( const char* src, unsigned char dst[256]);
+void CopyPascalStringToC( const unsigned char* src, char* dst);
+
+
+typedef struct AbsoluteTime
+{
+ unsigned long hi;
+ unsigned long lo;
+} AbsoluteTime;
+
+AbsoluteTime UpTime(); // NOTE: returns time since app started, not system start
+
+typedef long Duration;
+
+enum
+{
+ durationMicrosecond = -1,
+ durationMillisecond = 1,
+ durationSecond = 1000,
+ durationMinute = 1000 * 60,
+ durationHour = 1000 * 60 * 60,
+ durationDay = 1000 * 60 * 60 * 24,
+ durationForever = 0x7FFFFFFF,
+ durationImmediate = 0,
+};
+
+Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b);
+
+
+inline bool isnormal( double x)
+{
+ int ret = _fpclass( x);
+ return (ret == _FPCLASS_NN || ret == _FPCLASS_PN);
+}
+
+typedef unsigned int uintptr_t;
+
+
+// fix file names to use '/' instead of ':'
+char* ConvertFileName( const char* orgfilename);
+
+#define fopen( a, b) fopen( ConvertFileName( a), b);
+/*
+inline float abs( float f)
+{
+if (f < 0)
+return -f;
+return f;
+}
+
+inline double abs( double f)
+{
+if (f < 0)
+return -f;
+return f;
+}
+*/
+inline long long abs( long long f)
+{
+ if (f < 0)
+ return -f;
+ return f;
+}
+#endif
+#endif
\ No newline at end of file
--- /dev/null
+/**> HEADER FILES <**/
+#include "WinInput.h"
+#include "String.h"
+
+extern bool keyboardfrozen;
+extern bool buttons[3];
+/********************> IsKeyDown() <*****/
+Boolean IsKeyDown( unsigned char *keyMap, unsigned short theKey )
+{
+ if(keyboardfrozen)return 0;
+ if(theKey< 0x80 /*1000*/){
+ static long keyMapIndex;
+ static Boolean isKeyDown;
+ static short bitToCheck;
+
+ // Calculate the key map index
+ keyMapIndex = keyMap[theKey/8];
+
+ // Calculate the individual bit to check
+ bitToCheck = theKey%8;
+
+ // Check the status of the key
+ isKeyDown = ( keyMapIndex >> bitToCheck ) & 0x01;
+
+ // Return the status of the key
+ return isKeyDown;
+ }
+ else if(theKey==MAC_MOUSEBUTTON1)
+ return buttons[0];
+ else if(theKey==MAC_MOUSEBUTTON2)
+ return buttons[1];
+
+ return 0;
+}
+
+unsigned short CharToKey(char* which)
+{
+ // alphabetic keys
+ if(!stricmp(which,"a")){
+ return MAC_A_KEY;
+ }
+ if(!stricmp(which,"b")){
+ return MAC_B_KEY;
+ }
+ if(!stricmp(which,"c")){
+ return MAC_C_KEY;
+ }
+ if(!stricmp(which,"d")){
+ return MAC_D_KEY;
+ }
+ if(!stricmp(which,"e")){
+ return MAC_E_KEY;
+ }
+ if(!stricmp(which,"f")){
+ return MAC_F_KEY;
+ }
+ if(!stricmp(which,"g")){
+ return MAC_G_KEY;
+ }
+ if(!stricmp(which,"h")){
+ return MAC_H_KEY;
+ }
+ if(!stricmp(which,"i")){
+ return MAC_I_KEY;
+ }
+ if(!stricmp(which,"j")){
+ return MAC_J_KEY;
+ }
+ if(!stricmp(which,"k")){
+ return MAC_K_KEY;
+ }
+ if(!stricmp(which,"l")){
+ return MAC_L_KEY;
+ }
+ if(!stricmp(which,"m")){
+ return MAC_M_KEY;
+ }
+ if(!stricmp(which,"n")){
+ return MAC_N_KEY;
+ }
+ if(!stricmp(which,"o")){
+ return MAC_O_KEY;
+ }
+ if(!stricmp(which,"p")){
+ return MAC_P_KEY;
+ }
+ if(!stricmp(which,"q")){
+ return MAC_Q_KEY;
+ }
+ if(!stricmp(which,"r")){
+ return MAC_R_KEY;
+ }
+ if(!stricmp(which,"s")){
+ return MAC_S_KEY;
+ }
+ if(!stricmp(which,"t")){
+ return MAC_T_KEY;
+ }
+ if(!stricmp(which,"u")){
+ return MAC_U_KEY;
+ }
+ if(!stricmp(which,"v")){
+ return MAC_V_KEY;
+ }
+ if(!stricmp(which,"w")){
+ return MAC_W_KEY;
+ }
+ if(!stricmp(which,"x")){
+ return MAC_X_KEY;
+ }
+ if(!stricmp(which,"y")){
+ return MAC_Y_KEY;
+ }
+ if(!stricmp(which,"z")){
+ return MAC_Z_KEY;
+ }
+
+ // keypad keys
+ if(!stricmp(which,"KP0")){
+ return MAC_NUMPAD_0_KEY;
+ }
+ if(!stricmp(which,"KP1")){
+ return MAC_NUMPAD_1_KEY;
+ }
+ if(!stricmp(which,"KP2")){
+ return MAC_NUMPAD_2_KEY;
+ }
+ if(!stricmp(which,"KP3")){
+ return MAC_NUMPAD_3_KEY;
+ }
+ if(!stricmp(which,"KP4")){
+ return MAC_NUMPAD_4_KEY;
+ }
+ if(!stricmp(which,"KP5")){
+ return MAC_NUMPAD_5_KEY;
+ }
+ if(!stricmp(which,"KP6")){
+ return MAC_NUMPAD_6_KEY;
+ }
+ if(!stricmp(which,"KP7")){
+ return MAC_NUMPAD_7_KEY;
+ }
+ if(!stricmp(which,"KP8")){
+ return MAC_NUMPAD_8_KEY;
+ }
+ if(!stricmp(which,"KP9")){
+ return MAC_NUMPAD_9_KEY;
+ }
+
+ // enter
+ if(!stricmp(which,"enter")){
+ return MAC_ENTER_KEY;
+ }
+
+ // number keys
+ if(!stricmp(which,"0")){
+ return MAC_0_KEY;
+ }
+ if(!stricmp(which,"1")){
+ return MAC_1_KEY;
+ }
+ if(!stricmp(which,"2")){
+ return MAC_2_KEY;
+ }
+ if(!stricmp(which,"3")){
+ return MAC_3_KEY;
+ }
+ if(!stricmp(which,"4")){
+ return MAC_4_KEY;
+ }
+ if(!stricmp(which,"5")){
+ return MAC_5_KEY;
+ }
+ if(!stricmp(which,"6")){
+ return MAC_6_KEY;
+ }
+ if(!stricmp(which,"7")){
+ return MAC_7_KEY;
+ }
+ if(!stricmp(which,"8")){
+ return MAC_8_KEY;
+ }
+ if(!stricmp(which,"9")){
+ return MAC_9_KEY;
+ }
+
+ // function keys
+ if(!stricmp(which,"F1")){
+ return MAC_F1_KEY;
+ }
+ if(!stricmp(which,"F2")){
+ return MAC_F2_KEY;
+ }
+ if(!stricmp(which,"F3")){
+ return MAC_F3_KEY;
+ }
+ if(!stricmp(which,"F4")){
+ return MAC_F4_KEY;
+ }
+ if(!stricmp(which,"F5")){
+ return MAC_F5_KEY;
+ }
+ if(!stricmp(which,"F6")){
+ return MAC_F6_KEY;
+ }
+ if(!stricmp(which,"F7")){
+ return MAC_F7_KEY;
+ }
+ if(!stricmp(which,"F8")){
+ return MAC_F8_KEY;
+ }
+ if(!stricmp(which,"F9")){
+ return MAC_F9_KEY;
+ }
+ if(!stricmp(which,"F10")){
+ return MAC_F10_KEY;
+ }
+ if(!stricmp(which,"F11")){
+ return MAC_F11_KEY;
+ }
+ if(!stricmp(which,"F12")){
+ return MAC_F12_KEY;
+ }
+
+ // escape
+ if(!stricmp(which,"escape")){
+ return MAC_ESCAPE_KEY;
+ }
+ if(!stricmp(which,"backspace")){
+ return MAC_DELETE_KEY;
+ }
+ if(!stricmp(which,"tab")){
+ return MAC_TAB_KEY;
+ }
+ if(!stricmp(which,"`")){
+ return MAC_TILDE_KEY;
+ }
+ if(!stricmp(which,"caps_lock")){
+ return MAC_CAPS_LOCK_KEY;
+ }
+// if(which==){
+// return "";
+// }
+ if(!stricmp(which,"command")){
+ return MAC_COMMAND_KEY;
+ }
+ if(!stricmp(which,"option")){
+ return MAC_OPTION_KEY;
+ }
+ if(!stricmp(which,"delete")){
+ return MAC_DEL_KEY;
+ }
+ if(!stricmp(which,"insert")){
+ return MAC_INSERT_KEY;
+ }
+ if(!stricmp(which,"home")){
+ return MAC_HOME_KEY;
+ }
+ if(!stricmp(which,"end")){
+ return MAC_END_KEY;
+ }
+ if(!stricmp(which,"page_up")){
+ return MAC_PAGE_UP_KEY;
+ }
+ if(!stricmp(which,"page_down")){
+ return MAC_PAGE_DOWN_KEY;
+ }
+ if(!stricmp(which,"clear")){
+ return MAC_NUMPAD_CLEAR_KEY;
+ }
+
+ if(!stricmp(which,"control")){
+ return MAC_CONTROL_KEY;
+ }
+ if(!stricmp(which,"return")){
+ return MAC_RETURN_KEY;
+ }
+ if(!stricmp(which,"space")){
+ return MAC_SPACE_KEY;
+ }
+ if(!stricmp(which,"shift")){
+ return MAC_SHIFT_KEY;
+ }
+ if(!stricmp(which,"uparrow")){
+ return MAC_ARROW_UP_KEY;
+ }
+ if(!stricmp(which,"downarrow")){
+ return MAC_ARROW_DOWN_KEY;
+ }
+ if(!stricmp(which,"leftarrow")){
+ return MAC_ARROW_LEFT_KEY;
+ }
+ if(!stricmp(which,"rightarrow")){
+ return MAC_ARROW_RIGHT_KEY;
+ }
+ if(!stricmp(which,"mouse1")){
+ return MAC_MOUSEBUTTON1;
+ }
+ if(!stricmp(which,"mouse2")){
+ return MAC_MOUSEBUTTON2;
+ }
+ if(!stricmp(which,"+")){
+ return MAC_NUMPAD_PLUS_KEY;
+ }
+ if(!stricmp(which,"*")){
+ return MAC_NUMPAD_ASTERISK_KEY;
+ }
+ if(!stricmp(which,"/")){
+ return MAC_SLASH_KEY;
+ }
+ if(!stricmp(which,"\\")){
+ return MAC_BACKSLASH_KEY;
+ }
+ if(!stricmp(which,"[")){
+ return MAC_LEFTBRACKET_KEY;
+ }
+ if(!stricmp(which,"]")){
+ return MAC_RIGHTBRACKET_KEY;
+ }
+ if(!stricmp(which,".")){
+ return MAC_PERIOD_KEY;
+ }
+ if(!stricmp(which,",")){
+ return MAC_COMMA_KEY;
+ }
+ if(!stricmp(which,"\"")){
+ return MAC_APOSTROPHE_KEY;
+ }
+ if(!stricmp(which,";")){
+ return MAC_SEMICOLON_KEY;
+ }
+ return UNKNOWN_KEY;
+}
+
+char* KeyToChar(unsigned short which)
+{
+ static int i;
+
+ // alphabetic keys
+ if(which==MAC_A_KEY){
+ return "a";
+ }
+ if(which==MAC_B_KEY){
+ return "b";
+ }
+ if(which==MAC_C_KEY){
+ return "c";
+ }
+ if(which==MAC_D_KEY){
+ return "d";
+ }
+ if(which==MAC_E_KEY){
+ return "e";
+ }
+ if(which==MAC_F_KEY){
+ return "f";
+ }
+ if(which==MAC_G_KEY){
+ return "g";
+ }
+ if(which==MAC_H_KEY){
+ return "h";
+ }
+ if(which==MAC_I_KEY){
+ return "i";
+ }
+ if(which==MAC_J_KEY){
+ return "j";
+ }
+ if(which==MAC_K_KEY){
+ return "k";
+ }
+ if(which==MAC_L_KEY){
+ return "l";
+ }
+ if(which==MAC_M_KEY){
+ return "m";
+ }
+ if(which==MAC_N_KEY){
+ return "n";
+ }
+ if(which==MAC_O_KEY){
+ return "o";
+ }
+ if(which==MAC_P_KEY){
+ return "p";
+ }
+ if(which==MAC_Q_KEY){
+ return "q";
+ }
+ if(which==MAC_R_KEY){
+ return "r";
+ }
+ if(which==MAC_S_KEY){
+ return "s";
+ }
+ if(which==MAC_T_KEY){
+ return "t";
+ }
+ if(which==MAC_U_KEY){
+ return "u";
+ }
+ if(which==MAC_V_KEY){
+ return "v";
+ }
+ if(which==MAC_W_KEY){
+ return "w";
+ }
+ if(which==MAC_X_KEY){
+ return "x";
+ }
+ if(which==MAC_Y_KEY){
+ return "y";
+ }
+ if(which==MAC_Z_KEY){
+ return "z";
+ }
+
+ // keypad keys
+ if(which==MAC_NUMPAD_1_KEY){
+ return "KP1";
+ }
+ if(which==MAC_NUMPAD_2_KEY){
+ return "KP2";
+ }
+ if(which==MAC_NUMPAD_3_KEY){
+ return "KP3";
+ }
+ if(which==MAC_NUMPAD_4_KEY){
+ return "KP4";
+ }
+ if(which==MAC_NUMPAD_5_KEY){
+ return "KP5";
+ }
+ if(which==MAC_NUMPAD_6_KEY){
+ return "KP6";
+ }
+ if(which==MAC_NUMPAD_7_KEY){
+ return "KP7";
+ }
+ if(which==MAC_NUMPAD_8_KEY){
+ return "KP8";
+ }
+ if(which==MAC_NUMPAD_9_KEY){
+ return "KP9";
+ }
+ if(which==MAC_NUMPAD_0_KEY){
+ return "KP0";
+ }
+
+ // enter
+ if(which==MAC_ENTER_KEY){
+ return "enter";
+ }
+
+ // number keys
+ if(which==MAC_1_KEY){
+ return "1";
+ }
+ if(which==MAC_2_KEY){
+ return "2";
+ }
+ if(which==MAC_3_KEY){
+ return "3";
+ }
+ if(which==MAC_4_KEY){
+ return "4";
+ }
+ if(which==MAC_5_KEY){
+ return "5";
+ }
+ if(which==MAC_6_KEY){
+ return "6";
+ }
+ if(which==MAC_7_KEY){
+ return "7";
+ }
+ if(which==MAC_8_KEY){
+ return "8";
+ }
+ if(which==MAC_9_KEY){
+ return "9";
+ }
+ if(which==MAC_0_KEY){
+ return "0";
+ }
+
+ // function keys
+ if(which==MAC_F1_KEY){
+ return "F1";
+ }
+ if(which==MAC_F2_KEY){
+ return "F2";
+ }
+ if(which==MAC_F3_KEY){
+ return "F3";
+ }
+ if(which==MAC_F4_KEY){
+ return "F4";
+ }
+ if(which==MAC_F5_KEY){
+ return "F5";
+ }
+ if(which==MAC_F6_KEY){
+ return "F6";
+ }
+ if(which==MAC_F7_KEY){
+ return "F7";
+ }
+ if(which==MAC_F8_KEY){
+ return "F8";
+ }
+ if(which==MAC_F9_KEY){
+ return "F9";
+ }
+ if(which==MAC_F10_KEY){
+ return "F10";
+ }
+ if(which==MAC_F11_KEY){
+ return "F11";
+ }
+ if(which==MAC_F12_KEY){
+ return "F12";
+ }
+
+ // escape
+ if(which==MAC_ESCAPE_KEY){
+ return "escape";
+ }
+ if(which==MAC_DELETE_KEY){
+ return "backspace";
+ }
+ if(which==MAC_TAB_KEY){
+ return "tab";
+ }
+ if(which==MAC_TILDE_KEY){
+ return "`";
+ }
+ if(which==MAC_CAPS_LOCK_KEY){
+ return "caps_lock";
+ }
+ if(which==MAC_COMMAND_KEY){
+ return "command";
+ }
+ if(which==MAC_OPTION_KEY){
+ return "option";
+ }
+ if(which==MAC_DEL_KEY){
+ return "delete";
+ }
+ if(which==MAC_INSERT_KEY){
+ return "insert";
+ }
+ if(which==MAC_HOME_KEY){
+ return "home";
+ }
+ if(which==MAC_END_KEY){
+ return "end";
+ }
+ if(which==MAC_PAGE_UP_KEY){
+ return "page_up";
+ }
+ if(which==MAC_PAGE_DOWN_KEY){
+ return "page_down";
+ }
+ if(which==MAC_NUMPAD_CLEAR_KEY){
+ return "clear";
+ }
+ if(which==MAC_CONTROL_KEY){
+ return "control";
+ }
+ if(which==MAC_SPACE_KEY){
+ return "space";
+ }
+ if(which==MAC_RETURN_KEY){
+ return "return";
+ }
+ if(which==MAC_SHIFT_KEY){
+ return "shift";
+ }
+ if(which==MAC_ARROW_UP_KEY){
+ return "uparrow";
+ }
+ if(which==MAC_ARROW_DOWN_KEY){
+ return "downarrow";
+ }
+ if(which==MAC_ARROW_LEFT_KEY){
+ return "leftarrow";
+ }
+ if(which==MAC_ARROW_RIGHT_KEY){
+ return "rightarrow";
+ }
+ if(which==MAC_MOUSEBUTTON1){
+ return "mouse1";
+ }
+ if(which==MAC_MOUSEBUTTON2){
+ return "mouse2";
+ }
+ if(which==MAC_ARROW_RIGHT_KEY){
+ return "rightarrow";
+ }
+ if(which==MAC_MINUS_KEY||which==MAC_NUMPAD_MINUS_KEY){
+ return "-";
+ }
+ if(which==MAC_PLUS_KEY||which==MAC_NUMPAD_EQUALS_KEY){
+ return "=";
+ }
+ if(which==MAC_NUMPAD_PLUS_KEY){
+ return "+";
+ }
+ if(which==MAC_NUMPAD_ASTERISK_KEY){
+ return "*";
+ }
+ if(which==MAC_SLASH_KEY||which==MAC_NUMPAD_SLASH_KEY){
+ return "/";
+ }
+ if(which==MAC_BACKSLASH_KEY){
+ return "\\";
+ }
+ if(which==MAC_LEFTBRACKET_KEY){
+ return "[";
+ }
+ if(which==MAC_RIGHTBRACKET_KEY){
+ return "]";
+ }
+ if(which==MAC_PERIOD_KEY||which==MAC_NUMPAD_PERIOD_KEY){
+ return ".";
+ }
+ if(which==MAC_COMMA_KEY){
+ return ",";
+ }
+ if(which==MAC_APOSTROPHE_KEY){
+ return "\"";
+ }
+ if(which==MAC_SEMICOLON_KEY){
+ return ";";
+ }
+ return "unknown";
+}
+
+char KeyToSingleChar(unsigned short which)
+{
+ static int i;
+
+ if(which==MAC_A_KEY){
+ return 'a';
+ }
+ if(which==MAC_B_KEY){
+ return 'b';
+ }
+ if(which==MAC_C_KEY){
+ return 'c';
+ }
+ if(which==MAC_D_KEY){
+ return 'd';
+ }
+ if(which==MAC_E_KEY){
+ return 'e';
+ }
+ if(which==MAC_F_KEY){
+ return 'f';
+ }
+ if(which==MAC_G_KEY){
+ return 'g';
+ }
+ if(which==MAC_H_KEY){
+ return 'h';
+ }
+ if(which==MAC_I_KEY){
+ return 'i';
+ }
+ if(which==MAC_J_KEY){
+ return 'j';
+ }
+ if(which==MAC_K_KEY){
+ return 'k';
+ }
+ if(which==MAC_L_KEY){
+ return 'l';
+ }
+ if(which==MAC_M_KEY){
+ return 'm';
+ }
+ if(which==MAC_N_KEY){
+ return 'n';
+ }
+ if(which==MAC_O_KEY){
+ return 'o';
+ }
+ if(which==MAC_P_KEY){
+ return 'p';
+ }
+ if(which==MAC_Q_KEY){
+ return 'q';
+ }
+ if(which==MAC_R_KEY){
+ return 'r';
+ }
+ if(which==MAC_S_KEY){
+ return 's';
+ }
+ if(which==MAC_T_KEY){
+ return 't';
+ }
+ if(which==MAC_U_KEY){
+ return 'u';
+ }
+ if(which==MAC_V_KEY){
+ return 'v';
+ }
+ if(which==MAC_W_KEY){
+ return 'w';
+ }
+ if(which==MAC_X_KEY){
+ return 'x';
+ }
+ if(which==MAC_Y_KEY){
+ return 'y';
+ }
+ if(which==MAC_Z_KEY){
+ return 'z';
+ }
+ if(which==MAC_NUMPAD_1_KEY){
+ return '1';
+ }
+ if(which==MAC_NUMPAD_2_KEY){
+ return '2';
+ }
+ if(which==MAC_NUMPAD_3_KEY){
+ return '3';
+ }
+ if(which==MAC_NUMPAD_4_KEY){
+ return '4';
+ }
+ if(which==MAC_NUMPAD_5_KEY){
+ return '5';
+ }
+ if(which==MAC_NUMPAD_6_KEY){
+ return '6';
+ }
+ if(which==MAC_NUMPAD_7_KEY){
+ return '7';
+ }
+ if(which==MAC_NUMPAD_8_KEY){
+ return '8';
+ }
+ if(which==MAC_NUMPAD_9_KEY){
+ return '9';
+ }
+ if(which==MAC_NUMPAD_0_KEY){
+ return '0';
+ }
+ if(which==MAC_1_KEY){
+ return '1';
+ }
+ if(which==MAC_2_KEY){
+ return '2';
+ }
+ if(which==MAC_3_KEY){
+ return '3';
+ }
+ if(which==MAC_4_KEY){
+ return '4';
+ }
+ if(which==MAC_5_KEY){
+ return '5';
+ }
+ if(which==MAC_6_KEY){
+ return '6';
+ }
+ if(which==MAC_7_KEY){
+ return '7';
+ }
+ if(which==MAC_8_KEY){
+ return '8';
+ }
+ if(which==MAC_9_KEY){
+ return '9';
+ }
+ if(which==MAC_0_KEY){
+ return '0';
+ }
+ if(which==MAC_SPACE_KEY){
+ return ' ';
+ }
+ if(which==MAC_MINUS_KEY||which==MAC_NUMPAD_MINUS_KEY){
+ return '-';
+ }
+ if(which==MAC_PLUS_KEY||which==MAC_NUMPAD_EQUALS_KEY){
+ return '=';
+ }
+ if(which==MAC_NUMPAD_PLUS_KEY){
+ return '+';
+ }
+ if(which==MAC_NUMPAD_ASTERISK_KEY){
+ return '*';
+ }
+ if(which==MAC_SLASH_KEY||which==MAC_NUMPAD_SLASH_KEY){
+ return '/';
+ }
+ if(which==MAC_BACKSLASH_KEY){
+ return '\\';
+ }
+ if(which==MAC_LEFTBRACKET_KEY){
+ return '[';
+ }
+ if(which==MAC_RIGHTBRACKET_KEY){
+ return ']';
+ }
+ if(which==MAC_PERIOD_KEY||which==MAC_NUMPAD_PERIOD_KEY){
+ return '.';
+ }
+ if(which==MAC_COMMA_KEY){
+ return ',';
+ }
+ if(which==MAC_APOSTROPHE_KEY){
+ return '\'';
+ }
+ if(which==MAC_SEMICOLON_KEY){
+ return ';';
+ }
+ return '\0';
+}
+
+char Shift(char which)
+{
+ static int i;
+
+ if(which=='a'){
+ return 'A';
+ }
+ if(which=='b'){
+ return 'B';
+ }
+ if(which=='c'){
+ return 'C';
+ }
+ if(which=='d'){
+ return 'D';
+ }
+ if(which=='e'){
+ return 'E';
+ }
+ if(which=='f'){
+ return 'F';
+ }
+ if(which=='g'){
+ return 'G';
+ }
+ if(which=='h'){
+ return 'H';
+ }
+ if(which=='e'){
+ return 'E';
+ }
+ if(which=='f'){
+ return 'F';
+ }
+ if(which=='g'){
+ return 'G';
+ }
+ if(which=='h'){
+ return 'H';
+ }
+ if(which=='i'){
+ return 'I';
+ }
+ if(which=='j'){
+ return 'J';
+ }
+ if(which=='k'){
+ return 'K';
+ }
+ if(which=='l'){
+ return 'L';
+ }
+ if(which=='m'){
+ return 'M';
+ }
+ if(which=='n'){
+ return 'N';
+ }
+ if(which=='o'){
+ return 'O';
+ }
+ if(which=='p'){
+ return 'P';
+ }
+ if(which=='q'){
+ return 'Q';
+ }
+ if(which=='r'){
+ return 'R';
+ }
+ if(which=='s'){
+ return 'S';
+ }
+ if(which=='t'){
+ return 'T';
+ }
+ if(which=='u'){
+ return 'U';
+ }
+ if(which=='v'){
+ return 'V';
+ }
+ if(which=='w'){
+ return 'W';
+ }
+ if(which=='x'){
+ return 'X';
+ }
+ if(which=='y'){
+ return 'Y';
+ }
+ if(which=='z'){
+ return 'Z';
+ }
+ if(which=='1'){
+ return '!';
+ }
+ if(which=='2'){
+ return '@';
+ }
+ if(which=='3'){
+ return '#';
+ }
+ if(which=='4'){
+ return '$';
+ }
+ if(which=='5'){
+ return '%';
+ }
+ if(which=='6'){
+ return '^';
+ }
+ if(which=='7'){
+ return '&';
+ }
+ if(which=='8'){
+ return '*';
+ }
+ if(which=='9'){
+ return '(';
+ }
+ if(which=='0'){
+ return ')';
+ }
+ if(which=='-'){
+ return '_';
+ }
+ if(which=='='){
+ return '+';
+ }
+ if(which=='['){
+ return '{';
+ }
+ if(which==']'){
+ return '}';
+ }
+ if(which=='\\'){
+ return '|';
+ }
+ if(which=='.'){
+ return '>';
+ }
+ if(which==','){
+ return '<';
+ }
+ if(which=='/'){
+ return '?';
+ }
+ if(which==';'){
+ return ':';
+ }
+ if(which=='\''){
+ return '\"';
+ }
+ return which;
+}
+
+bool Compare(char *thestring, char *tocompare, int start, int end)
+{
+ static int i;
+ for(i=start;i<=end;i++){
+ if(thestring[i]!=tocompare[i-start]&&thestring[i]!=tocompare[i-start]+'A'-'a')return 0;
+ }
+ return 1;
+}
\ No newline at end of file
--- /dev/null
+#ifndef _WININPUT_H_
+#define _WININPUT_H_
+
+/**> HEADER FILES <**/
+#include <stdlib.h>
+#include <stdio.h>
+#include "WinDefs.h"
+
+/**> CONSTANT DECLARATIONS <**/
+// Mac Keyboard Codes
+#define MAC_1_KEY 0x12
+#define MAC_2_KEY 0x13
+#define MAC_3_KEY 0x14
+#define MAC_4_KEY 0x15
+#define MAC_5_KEY 0x17
+#define MAC_6_KEY 0x16
+#define MAC_7_KEY 0x1A
+#define MAC_8_KEY 0x1C
+#define MAC_9_KEY 0x19
+#define MAC_0_KEY 0x1D
+#define MAC_NUMPAD_1_KEY 0x53
+#define MAC_NUMPAD_2_KEY 0x54
+#define MAC_NUMPAD_3_KEY 0x55
+#define MAC_NUMPAD_4_KEY 0x56
+#define MAC_NUMPAD_5_KEY 0x57
+#define MAC_NUMPAD_6_KEY 0x58
+#define MAC_NUMPAD_7_KEY 0x59
+#define MAC_NUMPAD_8_KEY 0x5B
+#define MAC_NUMPAD_9_KEY 0x5C
+#define MAC_NUMPAD_0_KEY 0x52
+#define MAC_A_KEY 0x00
+#define MAC_B_KEY 0x0B
+#define MAC_C_KEY 0x08
+#define MAC_D_KEY 0x02
+#define MAC_E_KEY 0x0E
+#define MAC_F_KEY 0x03
+#define MAC_G_KEY 0x05
+#define MAC_H_KEY 0x04
+#define MAC_I_KEY 0x22
+#define MAC_J_KEY 0x26
+#define MAC_K_KEY 0x28
+#define MAC_L_KEY 0x25
+#define MAC_M_KEY 0x2E
+#define MAC_N_KEY 0x2D
+#define MAC_O_KEY 0x1F
+#define MAC_P_KEY 0x23
+#define MAC_Q_KEY 0x0C
+#define MAC_R_KEY 0x0F
+#define MAC_S_KEY 0x01
+#define MAC_T_KEY 0x11
+#define MAC_U_KEY 0x20
+#define MAC_V_KEY 0x09
+#define MAC_W_KEY 0x0D
+#define MAC_X_KEY 0x07
+#define MAC_Y_KEY 0x10
+#define MAC_Z_KEY 0x06
+#define MAC_F1_KEY 0x7A
+#define MAC_F2_KEY 0x78
+#define MAC_F3_KEY 0x63
+#define MAC_F4_KEY 0x76
+#define MAC_F5_KEY 0x60
+#define MAC_F6_KEY 0x61
+#define MAC_F7_KEY 0x62
+#define MAC_F8_KEY 0x64
+#define MAC_F9_KEY 0x65
+#define MAC_F10_KEY 0x6D
+#define MAC_F11_KEY 0x67
+#define MAC_F12_KEY 0x6F
+#define MAC_RETURN_KEY 0x24
+#define MAC_ENTER_KEY 0x4C
+#define MAC_TAB_KEY 0x30
+#define MAC_SPACE_KEY 0x31
+#define MAC_DELETE_KEY 0x33
+#define MAC_ESCAPE_KEY 0x35
+#define MAC_COMMAND_KEY 0x37
+#define MAC_SHIFT_KEY 0x38
+#define MAC_CAPS_LOCK_KEY 0x39
+#define MAC_OPTION_KEY 0x3A
+#define MAC_CONTROL_KEY 0x3B
+#define MAC_PAGE_UP_KEY 0x74
+#define MAC_PAGE_DOWN_KEY 0x79
+#define MAC_INSERT_KEY 0x72
+#define MAC_DEL_KEY 0x75
+#define MAC_HOME_KEY 0x73
+#define MAC_END_KEY 0x77
+#define MAC_LEFT_BRACKET_KEY 0x21
+#define MAC_RIGHT_BRACKET_KEY 0x1E
+#define MAC_ARROW_UP_KEY 0x7E
+#define MAC_ARROW_DOWN_KEY 0x7D
+#define MAC_ARROW_LEFT_KEY 0x7B
+#define MAC_ARROW_RIGHT_KEY 0x7C
+#define MAC_TILDE_KEY 0x32
+#define MAC_MINUS_KEY 0x1B
+#define MAC_PLUS_KEY 0x18
+#define MAC_SLASH_KEY 0x2C
+#define MAC_PERIOD_KEY 0x2F
+#define MAC_COMMA_KEY 0x2B
+#define MAC_BACKSLASH_KEY 0x2A
+#define MAC_LEFTBRACKET_KEY 0x21
+#define MAC_RIGHTBRACKET_KEY 0x1E
+#define MAC_NUMPAD_CLEAR_KEY 0x47
+#define MAC_NUMPAD_MINUS_KEY 0x4E
+#define MAC_NUMPAD_EQUALS_KEY 0x51
+#define MAC_NUMPAD_PLUS_KEY 0x45
+#define MAC_NUMPAD_SLASH_KEY 0x4B
+#define MAC_NUMPAD_ASTERISK_KEY 0x43
+#define MAC_NUMPAD_ENTER_KEY 0x4C
+#define MAC_NUMPAD_PERIOD_KEY 0x41
+#define MAC_SEMICOLON_KEY 0x29
+#define MAC_APOSTROPHE_KEY 0x27
+#define MAC_MOUSEBUTTON1 10000
+#define MAC_MOUSEBUTTON2 10001
+
+#define UNKNOWN_KEY 0xFF
+
+
+/**> FUNCTION PROTOTYPES <**/
+Boolean IsKeyDown( unsigned char *keyMap, unsigned short theKey );
+void InitMouse();
+void MoveMouse(int xcoord, int ycoord, Point *mouseloc);
+void RefreshMouse(Point *mouseloc);
+void DisposeMouse();
+unsigned short CharToKey(char* which);
+char* KeyToChar(unsigned short which);
+char KeyToSingleChar(unsigned short which);
+char Shift(char which);
+bool Compare(char *thestring, char *tocompare, int start, int end);
+
+
+typedef unsigned char KeyMap[16];
+void GetKeys( unsigned char theKeys[16]);
+
+Boolean Button();
+
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef binio_h
+#define binio_h
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ /*
+ Notes on format of format strings:
+ * whitespace is ignored
+ * each "group" consists of an optional count (defaults to 1),
+ an optional byte-order marker (defaults to H, "host-native"),
+ and a data-type specifier.
+ * when unpacking, each variable argument is a pointer to the
+ appropriate number of objects of the appropriate type.
+ * when packing, each variable argument is an object of the
+ appropriate type if the count is omitted, or a pointer to the
+ appropriate number of objects of the appropriate type if the
+ count is specified.
+ * the buffer supplied to pack/unpack must be of sufficient length
+ to hold all the data, or the behavior is unspecified.
+ * the file provided to the "f" versions of the functions must be
+ open in the appropriate mode, or the behavior is unspecified.
+ * the file supplied to funpackf must be of sufficient length to
+ hold all the data, or the behavior is unspecified.
+ * the behavior of all functions is unspecified if the format string
+ is incorrectly-formed.
+
+ Data-type specifiers:
+ x skipped byte; no corresponding argument
+ b byte
+ s two-byte two's-complement integer
+ i four-byte two's-complement integer
+ l eight-byte two's-complement integer
+ f four-byte IEEE754 float
+ d eight-byte IEEE754 double
+
+ Byte-order specifiers:
+ L little-endian
+ B big-endian
+ H host's native byte order
+ N network byte order
+ */
+
+#if defined(BinIO_STDINT_HEADER)
+#include BinIO_STDINT_HEADER
+ typedef float float32_t;
+ typedef double float64_t;
+#else
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned long uint32_t;
+#ifdef WIN32
+ typedef unsigned __int64 uint64_t;
+#else
+ typedef unsigned long long uint64_t;
+#endif
+ typedef float float32_t;
+ typedef double float64_t;
+#endif
+
+ typedef struct
+ {
+ float64_t d;
+ uint64_t l;
+ int i;
+ float32_t f;
+ uint16_t s;
+ uint8_t b;
+ }
+ test_data;
+
+ extern void packf ( const char *format, ...);
+ extern void spackf (void *buffer, const char *format, ...);
+ extern void fpackf (FILE *file, const char *format, ...);
+ extern void vspackf (void *buffer, const char *format, va_list args);
+ extern void vfpackf (FILE *file, const char *format, va_list args);
+
+ extern void unpackf ( const char *format, ...);
+ extern void sunpackf (const void *buffer, const char *format, ...);
+ extern void funpackf (FILE *file, const char *format, ...);
+ extern void vsunpackf(const void *buffer, const char *format, va_list args);
+ extern void vfunpackf(FILE *file, const char *format, va_list args);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null
+// wrapper for FMOD to account for filename conversions in windows
+
+#ifndef _FMODWRAPPER_H_
+#define _FMODWRAPPER_H_
+
+#include "fmod_header.h"
+#include "WinDefs.h"
+
+
+#ifdef WIN32
+
+#define FSOUND_Sample_Load( a, b, c, d) FSOUND_Sample_Load( a, ConvertFileName( b), c, d, 0);
+
+#endif
+
+
+#endif
--- /dev/null
+#ifndef _FMOD_ERRORS_H
+#define _FMOD_ERRORS_H
+
+static char *FMOD_ErrorString(int errcode)
+{
+ switch (errcode)
+ {
+ case FMOD_ERR_NONE: return "No errors";
+ case FMOD_ERR_BUSY: return "Cannot call this command after FSOUND_Init. Call FSOUND_Close first.";
+ case FMOD_ERR_UNINITIALIZED: return "This command failed because FSOUND_Init was not called";
+ case FMOD_ERR_PLAY: return "Playing the sound failed.";
+ case FMOD_ERR_INIT: return "Error initializing output device.";
+ case FMOD_ERR_ALLOCATED: return "The output device is already in use and cannot be reused.";
+ case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the features needed for this soundsystem (16bit stereo output)";
+ case FMOD_ERR_COOPERATIVELEVEL: return "Error setting cooperative level for hardware.";
+ case FMOD_ERR_CREATEBUFFER: return "Error creating hardware sound buffer.";
+ case FMOD_ERR_FILE_NOTFOUND: return "File not found";
+ case FMOD_ERR_FILE_FORMAT: return "Unknown file format";
+ case FMOD_ERR_FILE_BAD: return "Error loading file";
+ case FMOD_ERR_MEMORY: return "Not enough memory ";
+ case FMOD_ERR_VERSION: return "The version number of this file format is not supported";
+ case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function";
+ case FMOD_ERR_NO_EAX: return "Tried to use an EAX command on a non EAX enabled channel or output.";
+ case FMOD_ERR_CHANNEL_ALLOC: return "Failed to allocate a new channel";
+ case FMOD_ERR_RECORD: return "Recording not supported on this device";
+ case FMOD_ERR_MEDIAPLAYER: return "Required Mediaplayer codec is not installed";
+
+ default : return "Unknown error";
+ };
+}
+
+#endif
--- /dev/null
+/* ========================================================================================== */
+/* FMOD Main header file. Copyright (c), Firelight Technologies Pty, Ltd. 1999-2004. */
+/* ========================================================================================== */
+
+#ifndef _FMOD_H_
+#define _FMOD_H_
+
+/* ========================================================================================== */
+/* DEFINITIONS */
+/* ========================================================================================== */
+
+#if (!defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(_WIN64) && !defined(_WIN32_WCE) && !defined(_XBOX)) || (defined(__GNUC__) && defined(WIN32))
+ #ifndef __cdecl
+ #define __cdecl
+ #endif
+ #ifndef __stdcall
+ #define __stdcall
+ #endif
+#endif
+
+#if defined(_WIN32_WCE)
+ #define F_API _cdecl
+ #define F_CALLBACKAPI _cdecl
+#else
+ #define F_API __stdcall
+ #define F_CALLBACKAPI __stdcall
+#endif
+
+#ifdef DLL_EXPORTS
+ #define DLL_API __declspec(dllexport)
+#else
+ #if defined(__LCC__) || defined(__MINGW32__) || defined(__CYGWIN32__)
+ #define DLL_API F_API
+ #else
+ #define DLL_API
+ #endif /* __LCC__ || __MINGW32__ || __CYGWIN32__ */
+#endif /* DLL_EXPORTS */
+
+#define FMOD_VERSION 3.74f
+
+/*
+ FMOD defined types
+*/
+typedef struct FSOUND_SAMPLE FSOUND_SAMPLE;
+typedef struct FSOUND_STREAM FSOUND_STREAM;
+typedef struct FSOUND_DSPUNIT FSOUND_DSPUNIT;
+typedef struct FSOUND_SYNCPOINT FSOUND_SYNCPOINT;
+typedef struct FMUSIC_MODULE FMUSIC_MODULE;
+
+/*
+ Callback types
+*/
+typedef void * (F_CALLBACKAPI *FSOUND_OPENCALLBACK) (const char *name);
+typedef void (F_CALLBACKAPI *FSOUND_CLOSECALLBACK) (void *handle);
+typedef int (F_CALLBACKAPI *FSOUND_READCALLBACK) (void *buffer, int size, void *handle);
+typedef int (F_CALLBACKAPI *FSOUND_SEEKCALLBACK) (void *handle, int pos, signed char mode);
+typedef int (F_CALLBACKAPI *FSOUND_TELLCALLBACK) (void *handle);
+
+typedef void * (F_CALLBACKAPI *FSOUND_ALLOCCALLBACK) (unsigned int size);
+typedef void * (F_CALLBACKAPI *FSOUND_REALLOCCALLBACK) (void *ptr, unsigned int size);
+typedef void (F_CALLBACKAPI *FSOUND_FREECALLBACK) (void *ptr);
+
+typedef void * (F_CALLBACKAPI *FSOUND_DSPCALLBACK) (void *originalbuffer, void *newbuffer, int length, void *userdata);
+typedef signed char (F_CALLBACKAPI *FSOUND_STREAMCALLBACK) (FSOUND_STREAM *stream, void *buff, int len, void *userdata);
+typedef signed char (F_CALLBACKAPI *FSOUND_METADATACALLBACK)(char *name, char *value, void *userdata);
+typedef void (F_CALLBACKAPI *FMUSIC_CALLBACK) (FMUSIC_MODULE *mod, unsigned char param);
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ On failure of commands in FMOD, use FSOUND_GetError to attain what happened.
+
+ [SEE_ALSO]
+ FSOUND_GetError
+]
+*/
+enum FMOD_ERRORS
+{
+ FMOD_ERR_NONE, /* No errors */
+ FMOD_ERR_BUSY, /* Cannot call this command after FSOUND_Init. Call FSOUND_Close first. */
+ FMOD_ERR_UNINITIALIZED, /* This command failed because FSOUND_Init or FSOUND_SetOutput was not called */
+ FMOD_ERR_INIT, /* Error initializing output device. */
+ FMOD_ERR_ALLOCATED, /* Error initializing output device, but more specifically, the output device is already in use and cannot be reused. */
+ FMOD_ERR_PLAY, /* Playing the sound failed. */
+ FMOD_ERR_OUTPUT_FORMAT, /* Soundcard does not support the features needed for this soundsystem (16bit stereo output) */
+ FMOD_ERR_COOPERATIVELEVEL, /* Error setting cooperative level for hardware. */
+ FMOD_ERR_CREATEBUFFER, /* Error creating hardware sound buffer. */
+ FMOD_ERR_FILE_NOTFOUND, /* File not found */
+ FMOD_ERR_FILE_FORMAT, /* Unknown file format */
+ FMOD_ERR_FILE_BAD, /* Error loading file */
+ FMOD_ERR_MEMORY, /* Not enough memory or resources */
+ FMOD_ERR_VERSION, /* The version number of this file format is not supported */
+ FMOD_ERR_INVALID_PARAM, /* An invalid parameter was passed to this function */
+ FMOD_ERR_NO_EAX, /* Tried to use an EAX command on a non EAX enabled channel or output. */
+ FMOD_ERR_CHANNEL_ALLOC, /* Failed to allocate a new channel */
+ FMOD_ERR_RECORD, /* Recording is not supported on this machine */
+ FMOD_ERR_MEDIAPLAYER, /* Windows Media Player not installed so cannot play wma or use internet streaming. */
+ FMOD_ERR_CDDEVICE /* An error occured trying to open the specified CD device */
+};
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ These output types are used with FSOUND_SetOutput, to choose which output driver to use.
+
+ FSOUND_OUTPUT_DSOUND will not support hardware 3d acceleration if the sound card driver
+ does not support DirectX 6 Voice Manager Extensions.
+
+ FSOUND_OUTPUT_WINMM is recommended for NT and CE.
+
+ [SEE_ALSO]
+ FSOUND_SetOutput
+ FSOUND_GetOutput
+]
+*/
+enum FSOUND_OUTPUTTYPES
+{
+ FSOUND_OUTPUT_NOSOUND, /* NoSound driver, all calls to this succeed but do nothing. */
+ FSOUND_OUTPUT_WINMM, /* Windows Multimedia driver. */
+ FSOUND_OUTPUT_DSOUND, /* DirectSound driver. You need this to get EAX2 or EAX3 support, or FX api support. */
+ FSOUND_OUTPUT_A3D, /* A3D driver. */
+
+ FSOUND_OUTPUT_OSS, /* Linux/Unix OSS (Open Sound System) driver, i.e. the kernel sound drivers. */
+ FSOUND_OUTPUT_ESD, /* Linux/Unix ESD (Enlightment Sound Daemon) driver. */
+ FSOUND_OUTPUT_ALSA, /* Linux Alsa driver. */
+
+ FSOUND_OUTPUT_ASIO, /* Low latency ASIO driver */
+ FSOUND_OUTPUT_XBOX, /* Xbox driver */
+ FSOUND_OUTPUT_PS2, /* PlayStation 2 driver */
+ FSOUND_OUTPUT_MAC, /* Mac SoundManager driver */
+ FSOUND_OUTPUT_GC, /* Gamecube driver */
+
+ FSOUND_OUTPUT_NOSOUND_NONREALTIME /* This is the same as nosound, but the sound generation is driven by FSOUND_Update */
+};
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ These mixer types are used with FSOUND_SetMixer, to choose which mixer to use, or to act
+ upon for other reasons using FSOUND_GetMixer.
+ It is not nescessary to set the mixer. FMOD will autodetect the best mixer for you.
+
+ [SEE_ALSO]
+ FSOUND_SetMixer
+ FSOUND_GetMixer
+]
+*/
+enum FSOUND_MIXERTYPES
+{
+ FSOUND_MIXER_AUTODETECT, /* CE/PS2/GC Only - Non interpolating/low quality mixer. */
+ FSOUND_MIXER_BLENDMODE, /* Removed / obsolete. */
+ FSOUND_MIXER_MMXP5, /* Removed / obsolete. */
+ FSOUND_MIXER_MMXP6, /* Removed / obsolete. */
+
+ FSOUND_MIXER_QUALITY_AUTODETECT,/* All platforms - Autodetect the fastest quality mixer based on your cpu. */
+ FSOUND_MIXER_QUALITY_FPU, /* Win32/Linux only - Interpolating/volume ramping FPU mixer. */
+ FSOUND_MIXER_QUALITY_MMXP5, /* Win32/Linux only - Interpolating/volume ramping P5 MMX mixer. */
+ FSOUND_MIXER_QUALITY_MMXP6, /* Win32/Linux only - Interpolating/volume ramping ppro+ MMX mixer. */
+
+ FSOUND_MIXER_MONO, /* CE/PS2/GC only - MONO non interpolating/low quality mixer. For speed*/
+ FSOUND_MIXER_QUALITY_MONO, /* CE/PS2/GC only - MONO Interpolating mixer. For speed */
+
+ FSOUND_MIXER_MAX
+};
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ These definitions describe the type of song being played.
+
+ [SEE_ALSO]
+ FMUSIC_GetType
+]
+*/
+enum FMUSIC_TYPES
+{
+ FMUSIC_TYPE_NONE,
+ FMUSIC_TYPE_MOD, /* Protracker / Fasttracker */
+ FMUSIC_TYPE_S3M, /* ScreamTracker 3 */
+ FMUSIC_TYPE_XM, /* FastTracker 2 */
+ FMUSIC_TYPE_IT, /* Impulse Tracker. */
+ FMUSIC_TYPE_MIDI, /* MIDI file */
+ FMUSIC_TYPE_FSB /* FMOD Sample Bank file */
+};
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_DSP_PRIORITIES
+
+ [DESCRIPTION]
+ These default priorities are used by FMOD internal system DSP units. They describe the
+ position of the DSP chain, and the order of how audio processing is executed.
+ You can actually through the use of FSOUND_DSP_GetxxxUnit (where xxx is the name of the DSP
+ unit), disable or even change the priority of a DSP unit.
+
+ [SEE_ALSO]
+ FSOUND_DSP_Create
+ FSOUND_DSP_SetPriority
+ FSOUND_DSP_GetSpectrum
+]
+*/
+#define FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT 0 /* DSP CLEAR unit - done first */
+#define FSOUND_DSP_DEFAULTPRIORITY_SFXUNIT 100 /* DSP SFX unit - done second */
+#define FSOUND_DSP_DEFAULTPRIORITY_MUSICUNIT 200 /* DSP MUSIC unit - done third */
+#define FSOUND_DSP_DEFAULTPRIORITY_USER 300 /* User priority, use this as reference for your own DSP units */
+#define FSOUND_DSP_DEFAULTPRIORITY_FFTUNIT 900 /* This reads data for FSOUND_DSP_GetSpectrum, so it comes after user units */
+#define FSOUND_DSP_DEFAULTPRIORITY_CLIPANDCOPYUNIT 1000 /* DSP CLIP AND COPY unit - last */
+/* [DEFINE_END] */
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_CAPS
+
+ [DESCRIPTION]
+ Driver description bitfields. Use FSOUND_Driver_GetCaps to determine if a driver enumerated
+ has the settings you are after. The enumerated driver depends on the output mode, see
+ FSOUND_OUTPUTTYPES
+
+ [SEE_ALSO]
+ FSOUND_GetDriverCaps
+ FSOUND_OUTPUTTYPES
+]
+*/
+#define FSOUND_CAPS_HARDWARE 0x1 /* This driver supports hardware accelerated 3d sound. */
+#define FSOUND_CAPS_EAX2 0x2 /* This driver supports EAX 2 reverb */
+#define FSOUND_CAPS_EAX3 0x10 /* This driver supports EAX 3 reverb */
+/* [DEFINE_END] */
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_MODES
+
+ [DESCRIPTION]
+ Sample description bitfields, OR them together for loading and describing samples.
+ NOTE. If the file format being loaded already has a defined format, such as WAV or MP3, then
+ trying to override the pre-defined format with a new set of format flags will not work. For
+ example, an 8 bit WAV file will not load as 16bit if you specify FSOUND_16BITS. It will just
+ ignore the flag and go ahead loading it as 8bits. For these type of formats the only flags
+ you can specify that will really alter the behaviour of how it is loaded, are the following.
+ ---------
+ Looping behaviour - FSOUND_LOOP_OFF, FSOUND_LOOP_NORMAL, FSOUND_LOOP_BIDI
+ Load destination - FSOUND_HW3D, FSOUND_HW2D, FSOUND_2D
+ Loading behaviour - FSOUND_NONBLOCKING, FSOUND_LOADMEMORY, FSOUND_LOADRAW, FSOUND_MPEGACCURATE, FSOUND_MPEGHALFRATE, FSOUND_FORCEMONO
+ Playback behaviour - FSOUND_STREAMABLE, FSOUND_ENABLEFX
+ PlayStation 2 only - FSOUND_USECORE0, FSOUND_USECORE1, FSOUND_LOADMEMORYIOP
+ ---------
+ See flag descriptions for what these do.
+]
+*/
+#define FSOUND_LOOP_OFF 0x00000001 /* For non looping samples. */
+#define FSOUND_LOOP_NORMAL 0x00000002 /* For forward looping samples. */
+#define FSOUND_LOOP_BIDI 0x00000004 /* For bidirectional looping samples. (no effect if in hardware). */
+#define FSOUND_8BITS 0x00000008 /* For 8 bit samples. */
+#define FSOUND_16BITS 0x00000010 /* For 16 bit samples. */
+#define FSOUND_MONO 0x00000020 /* For mono samples. */
+#define FSOUND_STEREO 0x00000040 /* For stereo samples. */
+#define FSOUND_UNSIGNED 0x00000080 /* For user created source data containing unsigned samples. */
+#define FSOUND_SIGNED 0x00000100 /* For user created source data containing signed data. */
+#define FSOUND_DELTA 0x00000200 /* For user created source data stored as delta values. */
+#define FSOUND_IT214 0x00000400 /* For user created source data stored using IT214 compression. */
+#define FSOUND_IT215 0x00000800 /* For user created source data stored using IT215 compression. */
+#define FSOUND_HW3D 0x00001000 /* Attempts to make samples use 3d hardware acceleration. (if the card supports it) */
+#define FSOUND_2D 0x00002000 /* Tells software (not hardware) based sample not to be included in 3d processing. */
+#define FSOUND_STREAMABLE 0x00004000 /* For a streamimg sound where you feed the data to it. */
+#define FSOUND_LOADMEMORY 0x00008000 /* "name" will be interpreted as a pointer to data for streaming and samples. */
+#define FSOUND_LOADRAW 0x00010000 /* Will ignore file format and treat as raw pcm. */
+#define FSOUND_MPEGACCURATE 0x00020000 /* For FSOUND_Stream_Open - for accurate FSOUND_Stream_GetLengthMs/FSOUND_Stream_SetTime. WARNING, see FSOUND_Stream_Open for inital opening time performance issues. */
+#define FSOUND_FORCEMONO 0x00040000 /* For forcing stereo streams and samples to be mono - needed if using FSOUND_HW3D and stereo data - incurs a small speed hit for streams */
+#define FSOUND_HW2D 0x00080000 /* 2D hardware sounds. allows hardware specific effects */
+#define FSOUND_ENABLEFX 0x00100000 /* Allows DX8 FX to be played back on a sound. Requires DirectX 8 - Note these sounds cannot be played more than once, be 8 bit, be less than a certain size, or have a changing frequency */
+#define FSOUND_MPEGHALFRATE 0x00200000 /* For FMODCE only - decodes mpeg streams using a lower quality decode, but faster execution */
+#define FSOUND_IMAADPCM 0x00400000 /* Contents are stored compressed as IMA ADPCM */
+#define FSOUND_VAG 0x00800000 /* For PS2 only - Contents are compressed as Sony VAG format */
+#define FSOUND_NONBLOCKING 0x01000000 /* For FSOUND_Stream_Open/FMUSIC_LoadSong - Causes stream or music to open in the background and not block the foreground app. See FSOUND_Stream_GetOpenState or FMUSIC_GetOpenState to determine when it IS ready. */
+#define FSOUND_GCADPCM 0x02000000 /* For Gamecube only - Contents are compressed as Gamecube DSP-ADPCM format */
+#define FSOUND_MULTICHANNEL 0x04000000 /* For PS2 and Gamecube only - Contents are interleaved into a multi-channel (more than stereo) format */
+#define FSOUND_USECORE0 0x08000000 /* For PS2 only - Sample/Stream is forced to use hardware voices 00-23 */
+#define FSOUND_USECORE1 0x10000000 /* For PS2 only - Sample/Stream is forced to use hardware voices 24-47 */
+#define FSOUND_LOADMEMORYIOP 0x20000000 /* For PS2 only - "name" will be interpreted as a pointer to data for streaming and samples. The address provided will be an IOP address */
+#define FSOUND_IGNORETAGS 0x40000000 /* Skips id3v2 etc tag checks when opening a stream, to reduce seek/read overhead when opening files (helps with CD performance) */
+#define FSOUND_STREAM_NET 0x80000000 /* Specifies an internet stream */
+
+#define FSOUND_NORMAL (FSOUND_16BITS | FSOUND_SIGNED | FSOUND_MONO)
+/* [DEFINE_END] */
+
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_CDPLAYMODES
+
+ [DESCRIPTION]
+ Playback method for a CD Audio track, with FSOUND_CD_SetPlayMode
+
+ [SEE_ALSO]
+ FSOUND_CD_SetPlayMode
+ FSOUND_CD_Play
+]
+*/
+#define FSOUND_CD_PLAYCONTINUOUS 0 /* Starts from the current track and plays to end of CD. */
+#define FSOUND_CD_PLAYONCE 1 /* Plays the specified track then stops. */
+#define FSOUND_CD_PLAYLOOPED 2 /* Plays the specified track looped, forever until stopped manually. */
+#define FSOUND_CD_PLAYRANDOM 3 /* Plays tracks in random order */
+/* [DEFINE_END] */
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_MISC_VALUES
+
+ [DESCRIPTION]
+ Miscellaneous values for FMOD functions.
+
+ [SEE_ALSO]
+ FSOUND_PlaySound
+ FSOUND_PlaySoundEx
+ FSOUND_Sample_Alloc
+ FSOUND_Sample_Load
+ FSOUND_SetPan
+]
+*/
+#define FSOUND_FREE -1 /* value to play on any free channel, or to allocate a sample in a free sample slot. */
+#define FSOUND_UNMANAGED -2 /* value to allocate a sample that is NOT managed by FSOUND or placed in a sample slot. */
+#define FSOUND_ALL -3 /* for a channel index , this flag will affect ALL channels available! Not supported by every function. */
+#define FSOUND_STEREOPAN -1 /* value for FSOUND_SetPan so that stereo sounds are not played at half volume. See FSOUND_SetPan for more on this. */
+#define FSOUND_SYSTEMCHANNEL -1000 /* special 'channel' ID for all channel based functions that want to alter the global FSOUND software mixing output channel */
+#define FSOUND_SYSTEMSAMPLE -1000 /* special 'sample' ID for all sample based functions that want to alter the global FSOUND software mixing output sample */
+
+/* [DEFINE_END] */
+
+
+/*
+[STRUCTURE]
+[
+ [DESCRIPTION]
+ Structure defining a reverb environment.
+ For more indepth descriptions of the reverb properties under win32, please see the EAX2 and EAX3
+ documentation at http://developer.creative.com/ under the 'downloads' section.
+ If they do not have the EAX3 documentation, then most information can be attained from
+ the EAX2 documentation, as EAX3 only adds some more parameters and functionality on top of EAX2.
+ Note the default reverb properties are the same as the FSOUND_PRESET_GENERIC preset.
+ Note that integer values that typically range from -10,000 to 1000 are represented in decibels, and are of a logarithmic scale, not linear, wheras float values are typically linear.
+ PORTABILITY: Each member has the platform it supports in braces ie (win32/xbox).
+ Some reverb parameters are only supported in win32 and some only on xbox. If all parameters are set then the reverb should product a similar effect on either platform.
+
+ The numerical values listed below are the maximum, minimum and default values for each variable respectively.
+
+ [SEE_ALSO]
+ FSOUND_Reverb_SetProperties
+ FSOUND_Reverb_GetProperties
+ FSOUND_REVERB_PRESETS
+ FSOUND_REVERB_FLAGS
+]
+*/
+typedef struct _FSOUND_REVERB_PROPERTIES /* MIN MAX DEFAULT DESCRIPTION */
+{
+ unsigned int Environment; /* 0 , 25 , 0 , sets all listener properties (WIN32/PS2 only) */
+ float EnvSize; /* 1.0 , 100.0 , 7.5 , environment size in meters (WIN32 only) */
+ float EnvDiffusion; /* 0.0 , 1.0 , 1.0 , environment diffusion (WIN32/XBOX) */
+ int Room; /* -10000, 0 , -1000 , room effect level (at mid frequencies) (WIN32/XBOX/PS2) */
+ int RoomHF; /* -10000, 0 , -100 , relative room effect level at high frequencies (WIN32/XBOX) */
+ int RoomLF; /* -10000, 0 , 0 , relative room effect level at low frequencies (WIN32 only) */
+ float DecayTime; /* 0.1 , 20.0 , 1.49 , reverberation decay time at mid frequencies (WIN32/XBOX) */
+ float DecayHFRatio; /* 0.1 , 2.0 , 0.83 , high-frequency to mid-frequency decay time ratio (WIN32/XBOX) */
+ float DecayLFRatio; /* 0.1 , 2.0 , 1.0 , low-frequency to mid-frequency decay time ratio (WIN32 only) */
+ int Reflections; /* -10000, 1000 , -2602 , early reflections level relative to room effect (WIN32/XBOX) */
+ float ReflectionsDelay; /* 0.0 , 0.3 , 0.007 , initial reflection delay time (WIN32/XBOX) */
+ float ReflectionsPan[3]; /* , , [0,0,0], early reflections panning vector (WIN32 only) */
+ int Reverb; /* -10000, 2000 , 200 , late reverberation level relative to room effect (WIN32/XBOX) */
+ float ReverbDelay; /* 0.0 , 0.1 , 0.011 , late reverberation delay time relative to initial reflection (WIN32/XBOX) */
+ float ReverbPan[3]; /* , , [0,0,0], late reverberation panning vector (WIN32 only) */
+ float EchoTime; /* .075 , 0.25 , 0.25 , echo time (WIN32/PS2 only. PS2 = Delay time for ECHO/DELAY modes only) */
+ float EchoDepth; /* 0.0 , 1.0 , 0.0 , echo depth (WIN32/PS2 only. PS2 = Feedback level for ECHO mode only) */
+ float ModulationTime; /* 0.04 , 4.0 , 0.25 , modulation time (WIN32 only) */
+ float ModulationDepth; /* 0.0 , 1.0 , 0.0 , modulation depth (WIN32 only) */
+ float AirAbsorptionHF; /* -100 , 0.0 , -5.0 , change in level per meter at high frequencies (WIN32 only) */
+ float HFReference; /* 1000.0, 20000 , 5000.0 , reference high frequency (hz) (WIN32/XBOX) */
+ float LFReference; /* 20.0 , 1000.0, 250.0 , reference low frequency (hz) (WIN32 only) */
+ float RoomRolloffFactor; /* 0.0 , 10.0 , 0.0 , like FSOUND_3D_SetRolloffFactor but for room effect (WIN32/XBOX) */
+ float Diffusion; /* 0.0 , 100.0 , 100.0 , Value that controls the echo density in the late reverberation decay. (XBOX only) */
+ float Density; /* 0.0 , 100.0 , 100.0 , Value that controls the modal density in the late reverberation decay (XBOX only) */
+ unsigned int Flags; /* FSOUND_REVERB_FLAGS - modifies the behavior of above properties (WIN32/PS2 only) */
+} FSOUND_REVERB_PROPERTIES;
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_REVERB_FLAGS
+
+ [DESCRIPTION]
+ Values for the Flags member of the FSOUND_REVERB_PROPERTIES structure.
+
+ [SEE_ALSO]
+ FSOUND_REVERB_PROPERTIES
+]
+*/
+#define FSOUND_REVERB_FLAGS_DECAYTIMESCALE 0x00000001 /* 'EnvSize' affects reverberation decay time */
+#define FSOUND_REVERB_FLAGS_REFLECTIONSSCALE 0x00000002 /* 'EnvSize' affects reflection level */
+#define FSOUND_REVERB_FLAGS_REFLECTIONSDELAYSCALE 0x00000004 /* 'EnvSize' affects initial reflection delay time */
+#define FSOUND_REVERB_FLAGS_REVERBSCALE 0x00000008 /* 'EnvSize' affects reflections level */
+#define FSOUND_REVERB_FLAGS_REVERBDELAYSCALE 0x00000010 /* 'EnvSize' affects late reverberation delay time */
+#define FSOUND_REVERB_FLAGS_DECAYHFLIMIT 0x00000020 /* AirAbsorptionHF affects DecayHFRatio */
+#define FSOUND_REVERB_FLAGS_ECHOTIMESCALE 0x00000040 /* 'EnvSize' affects echo time */
+#define FSOUND_REVERB_FLAGS_MODULATIONTIMESCALE 0x00000080 /* 'EnvSize' affects modulation time */
+#define FSOUND_REVERB_FLAGS_CORE0 0x00000100 /* PS2 Only - Reverb is applied to CORE0 (hw voices 0-23) */
+#define FSOUND_REVERB_FLAGS_CORE1 0x00000200 /* PS2 Only - Reverb is applied to CORE1 (hw voices 24-47) */
+#define FSOUND_REVERB_FLAGS_DEFAULT (FSOUND_REVERB_FLAGS_DECAYTIMESCALE | \
+ FSOUND_REVERB_FLAGS_REFLECTIONSSCALE | \
+ FSOUND_REVERB_FLAGS_REFLECTIONSDELAYSCALE | \
+ FSOUND_REVERB_FLAGS_REVERBSCALE | \
+ FSOUND_REVERB_FLAGS_REVERBDELAYSCALE | \
+ FSOUND_REVERB_FLAGS_DECAYHFLIMIT | \
+ FSOUND_REVERB_FLAGS_CORE0 | \
+ FSOUND_REVERB_FLAGS_CORE1 )
+/* [DEFINE_END] */
+
+
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_REVERB_PRESETS
+
+ [DESCRIPTION]
+ A set of predefined environment PARAMETERS, created by Creative Labs
+ These are used to initialize an FSOUND_REVERB_PROPERTIES structure statically.
+ ie
+ FSOUND_REVERB_PROPERTIES prop = FSOUND_PRESET_GENERIC;
+
+ [SEE_ALSO]
+ FSOUND_Reverb_SetProperties
+]
+*/
+/* Env Size Diffus Room RoomHF RmLF DecTm DecHF DecLF Refl RefDel RefPan Revb RevDel ReverbPan EchoTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff Diffus Densty FLAGS */
+#define FSOUND_PRESET_OFF {0, 7.5f, 1.00f, -10000, -10000, 0, 1.00f, 1.00f, 1.0f, -2602, 0.007f, { 0.0f,0.0f,0.0f }, 200, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 0.0f, 0.0f, 0x33f }
+#define FSOUND_PRESET_GENERIC {0, 7.5f, 1.00f, -1000, -100, 0, 1.49f, 0.83f, 1.0f, -2602, 0.007f, { 0.0f,0.0f,0.0f }, 200, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_PADDEDCELL {1, 1.4f, 1.00f, -1000, -6000, 0, 0.17f, 0.10f, 1.0f, -1204, 0.001f, { 0.0f,0.0f,0.0f }, 207, 0.002f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_ROOM {2, 1.9f, 1.00f, -1000, -454, 0, 0.40f, 0.83f, 1.0f, -1646, 0.002f, { 0.0f,0.0f,0.0f }, 53, 0.003f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_BATHROOM {3, 1.4f, 1.00f, -1000, -1200, 0, 1.49f, 0.54f, 1.0f, -370, 0.007f, { 0.0f,0.0f,0.0f }, 1030, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 60.0f, 0x3f }
+#define FSOUND_PRESET_LIVINGROOM {4, 2.5f, 1.00f, -1000, -6000, 0, 0.50f, 0.10f, 1.0f, -1376, 0.003f, { 0.0f,0.0f,0.0f }, -1104, 0.004f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_STONEROOM {5, 11.6f, 1.00f, -1000, -300, 0, 2.31f, 0.64f, 1.0f, -711, 0.012f, { 0.0f,0.0f,0.0f }, 83, 0.017f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_AUDITORIUM {6, 21.6f, 1.00f, -1000, -476, 0, 4.32f, 0.59f, 1.0f, -789, 0.020f, { 0.0f,0.0f,0.0f }, -289, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_CONCERTHALL {7, 19.6f, 1.00f, -1000, -500, 0, 3.92f, 0.70f, 1.0f, -1230, 0.020f, { 0.0f,0.0f,0.0f }, -2, 0.029f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_CAVE {8, 14.6f, 1.00f, -1000, 0, 0, 2.91f, 1.30f, 1.0f, -602, 0.015f, { 0.0f,0.0f,0.0f }, -302, 0.022f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }
+#define FSOUND_PRESET_ARENA {9, 36.2f, 1.00f, -1000, -698, 0, 7.24f, 0.33f, 1.0f, -1166, 0.020f, { 0.0f,0.0f,0.0f }, 16, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_HANGAR {10, 50.3f, 1.00f, -1000, -1000, 0, 10.05f, 0.23f, 1.0f, -602, 0.020f, { 0.0f,0.0f,0.0f }, 198, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_CARPETTEDHALLWAY {11, 1.9f, 1.00f, -1000, -4000, 0, 0.30f, 0.10f, 1.0f, -1831, 0.002f, { 0.0f,0.0f,0.0f }, -1630, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_HALLWAY {12, 1.8f, 1.00f, -1000, -300, 0, 1.49f, 0.59f, 1.0f, -1219, 0.007f, { 0.0f,0.0f,0.0f }, 441, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_STONECORRIDOR {13, 13.5f, 1.00f, -1000, -237, 0, 2.70f, 0.79f, 1.0f, -1214, 0.013f, { 0.0f,0.0f,0.0f }, 395, 0.020f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_ALLEY {14, 7.5f, 0.30f, -1000, -270, 0, 1.49f, 0.86f, 1.0f, -1204, 0.007f, { 0.0f,0.0f,0.0f }, -4, 0.011f, { 0.0f,0.0f,0.0f }, 0.125f, 0.95f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_FOREST {15, 38.0f, 0.30f, -1000, -3300, 0, 1.49f, 0.54f, 1.0f, -2560, 0.162f, { 0.0f,0.0f,0.0f }, -229, 0.088f, { 0.0f,0.0f,0.0f }, 0.125f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 79.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_CITY {16, 7.5f, 0.50f, -1000, -800, 0, 1.49f, 0.67f, 1.0f, -2273, 0.007f, { 0.0f,0.0f,0.0f }, -1691, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 50.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_MOUNTAINS {17, 100.0f, 0.27f, -1000, -2500, 0, 1.49f, 0.21f, 1.0f, -2780, 0.300f, { 0.0f,0.0f,0.0f }, -1434, 0.100f, { 0.0f,0.0f,0.0f }, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 27.0f, 100.0f, 0x1f }
+#define FSOUND_PRESET_QUARRY {18, 17.5f, 1.00f, -1000, -1000, 0, 1.49f, 0.83f, 1.0f, -10000, 0.061f, { 0.0f,0.0f,0.0f }, 500, 0.025f, { 0.0f,0.0f,0.0f }, 0.125f, 0.70f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_PLAIN {19, 42.5f, 0.21f, -1000, -2000, 0, 1.49f, 0.50f, 1.0f, -2466, 0.179f, { 0.0f,0.0f,0.0f }, -1926, 0.100f, { 0.0f,0.0f,0.0f }, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 21.0f, 100.0f, 0x3f }
+#define FSOUND_PRESET_PARKINGLOT {20, 8.3f, 1.00f, -1000, 0, 0, 1.65f, 1.50f, 1.0f, -1363, 0.008f, { 0.0f,0.0f,0.0f }, -1153, 0.012f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }
+#define FSOUND_PRESET_SEWERPIPE {21, 1.7f, 0.80f, -1000, -1000, 0, 2.81f, 0.14f, 1.0f, 429, 0.014f, { 0.0f,0.0f,0.0f }, 1023, 0.021f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 80.0f, 60.0f, 0x3f }
+#define FSOUND_PRESET_UNDERWATER {22, 1.8f, 1.00f, -1000, -4000, 0, 1.49f, 0.10f, 1.0f, -449, 0.007f, { 0.0f,0.0f,0.0f }, 1700, 0.011f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 1.18f, 0.348f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }
+
+/* Non I3DL2 presets */
+
+#define FSOUND_PRESET_DRUGGED {23, 1.9f, 0.50f, -1000, 0, 0, 8.39f, 1.39f, 1.0f, -115, 0.002f, { 0.0f,0.0f,0.0f }, 985, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 0.25f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }
+#define FSOUND_PRESET_DIZZY {24, 1.8f, 0.60f, -1000, -400, 0, 17.23f, 0.56f, 1.0f, -1713, 0.020f, { 0.0f,0.0f,0.0f }, -613, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 1.00f, 0.81f, 0.310f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }
+#define FSOUND_PRESET_PSYCHOTIC {25, 1.0f, 0.50f, -1000, -151, 0, 7.56f, 0.91f, 1.0f, -626, 0.020f, { 0.0f,0.0f,0.0f }, 774, 0.030f, { 0.0f,0.0f,0.0f }, 0.250f, 0.00f, 4.00f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }
+
+/* PlayStation 2 Only presets */
+
+#define FSOUND_PRESET_PS2_ROOM {1, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_STUDIO_A {2, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_STUDIO_B {3, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_STUDIO_C {4, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_HALL {5, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_SPACE {6, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_ECHO {7, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_DELAY {8, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+#define FSOUND_PRESET_PS2_PIPE {9, 0, 0, 0, 0, 0, 0.0f, 0.0f, 0.0f, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0, 0.000f, { 0.0f,0.0f,0.0f }, 0.000f, 0.00f, 0.00f, 0.000f, 0.0f, 0000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0x31f }
+
+/* [DEFINE_END] */
+
+
+/*
+[STRUCTURE]
+[
+ [DESCRIPTION]
+ Structure defining the properties for a reverb source, related to a FSOUND channel.
+ For more indepth descriptions of the reverb properties under win32, please see the EAX3
+ documentation at http://developer.creative.com/ under the 'downloads' section.
+ If they do not have the EAX3 documentation, then most information can be attained from
+ the EAX2 documentation, as EAX3 only adds some more parameters and functionality on top of
+ EAX2.
+
+ Note the default reverb properties are the same as the FSOUND_PRESET_GENERIC preset.
+ Note that integer values that typically range from -10,000 to 1000 are represented in
+ decibels, and are of a logarithmic scale, not linear, wheras float values are typically linear.
+ PORTABILITY: Each member has the platform it supports in braces ie (win32/xbox).
+ Some reverb parameters are only supported in win32 and some only on xbox. If all parameters are set then
+ the reverb should product a similar effect on either platform.
+ Linux and FMODCE do not support the reverb api.
+
+ The numerical values listed below are the maximum, minimum and default values for each variable respectively.
+
+ [SEE_ALSO]
+ FSOUND_Reverb_SetChannelProperties
+ FSOUND_Reverb_GetChannelProperties
+ FSOUND_REVERB_CHANNELFLAGS
+]
+*/
+typedef struct _FSOUND_REVERB_CHANNELPROPERTIES /* MIN MAX DEFAULT */
+{
+ int Direct; /* -10000, 1000, 0, direct path level (at low and mid frequencies) (WIN32/XBOX) */
+ int DirectHF; /* -10000, 0, 0, relative direct path level at high frequencies (WIN32/XBOX) */
+ int Room; /* -10000, 1000, 0, room effect level (at low and mid frequencies) (WIN32/XBOX/PS2) */
+ int RoomHF; /* -10000, 0, 0, relative room effect level at high frequencies (WIN32/XBOX) */
+ int Obstruction; /* -10000, 0, 0, main obstruction control (attenuation at high frequencies) (WIN32/XBOX) */
+ float ObstructionLFRatio; /* 0.0, 1.0, 0.0, obstruction low-frequency level re. main control (WIN32/XBOX) */
+ int Occlusion; /* -10000, 0, 0, main occlusion control (attenuation at high frequencies) (WIN32/XBOX) */
+ float OcclusionLFRatio; /* 0.0, 1.0, 0.25, occlusion low-frequency level re. main control (WIN32/XBOX) */
+ float OcclusionRoomRatio; /* 0.0, 10.0, 1.5, relative occlusion control for room effect (WIN32) */
+ float OcclusionDirectRatio; /* 0.0, 10.0, 1.0, relative occlusion control for direct path (WIN32) */
+ int Exclusion; /* -10000, 0, 0, main exlusion control (attenuation at high frequencies) (WIN32) */
+ float ExclusionLFRatio; /* 0.0, 1.0, 1.0, exclusion low-frequency level re. main control (WIN32) */
+ int OutsideVolumeHF; /* -10000, 0, 0, outside sound cone level at high frequencies (WIN32) */
+ float DopplerFactor; /* 0.0, 10.0, 0.0, like DS3D flDopplerFactor but per source (WIN32) */
+ float RolloffFactor; /* 0.0, 10.0, 0.0, like DS3D flRolloffFactor but per source (WIN32) */
+ float RoomRolloffFactor; /* 0.0, 10.0, 0.0, like DS3D flRolloffFactor but for room effect (WIN32/XBOX) */
+ float AirAbsorptionFactor; /* 0.0, 10.0, 1.0, multiplies AirAbsorptionHF member of FSOUND_REVERB_PROPERTIES (WIN32) */
+ int Flags; /* FSOUND_REVERB_CHANNELFLAGS - modifies the behavior of properties (WIN32) */
+} FSOUND_REVERB_CHANNELPROPERTIES;
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_REVERB_CHANNELFLAGS
+
+ [DESCRIPTION]
+ Values for the Flags member of the FSOUND_REVERB_CHANNELPROPERTIES structure.
+
+ [SEE_ALSO]
+ FSOUND_REVERB_CHANNELPROPERTIES
+]
+*/
+#define FSOUND_REVERB_CHANNELFLAGS_DIRECTHFAUTO 0x00000001 /* Automatic setting of 'Direct' due to distance from listener */
+#define FSOUND_REVERB_CHANNELFLAGS_ROOMAUTO 0x00000002 /* Automatic setting of 'Room' due to distance from listener */
+#define FSOUND_REVERB_CHANNELFLAGS_ROOMHFAUTO 0x00000004 /* Automatic setting of 'RoomHF' due to distance from listener */
+#define FSOUND_REVERB_CHANNELFLAGS_DEFAULT (FSOUND_REVERB_CHANNELFLAGS_DIRECTHFAUTO | \
+ FSOUND_REVERB_CHANNELFLAGS_ROOMAUTO| \
+ FSOUND_REVERB_CHANNELFLAGS_ROOMHFAUTO)
+/* [DEFINE_END] */
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ These values are used with FSOUND_FX_Enable to enable DirectX 8 FX for a channel.
+
+ [SEE_ALSO]
+ FSOUND_FX_Enable
+ FSOUND_FX_Disable
+ FSOUND_FX_SetChorus
+ FSOUND_FX_SetCompressor
+ FSOUND_FX_SetDistortion
+ FSOUND_FX_SetEcho
+ FSOUND_FX_SetFlanger
+ FSOUND_FX_SetGargle
+ FSOUND_FX_SetI3DL2Reverb
+ FSOUND_FX_SetParamEQ
+ FSOUND_FX_SetWavesReverb
+]
+*/
+enum FSOUND_FX_MODES
+{
+ FSOUND_FX_CHORUS,
+ FSOUND_FX_COMPRESSOR,
+ FSOUND_FX_DISTORTION,
+ FSOUND_FX_ECHO,
+ FSOUND_FX_FLANGER,
+ FSOUND_FX_GARGLE,
+ FSOUND_FX_I3DL2REVERB,
+ FSOUND_FX_PARAMEQ,
+ FSOUND_FX_WAVES_REVERB,
+
+ FSOUND_FX_MAX
+};
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ These are speaker types defined for use with the FSOUND_SetSpeakerMode command.
+ Note - Only reliably works with FSOUND_OUTPUT_DSOUND or FSOUND_OUTPUT_XBOX output modes. Other output modes will only
+ interpret FSOUND_SPEAKERMODE_MONO and set everything else to be stereo.
+
+ Using either DolbyDigital or DTS will use whatever 5.1 digital mode is available if destination hardware is unsure.
+
+ [SEE_ALSO]
+ FSOUND_SetSpeakerMode
+
+]
+*/
+enum FSOUND_SPEAKERMODES
+{
+ FSOUND_SPEAKERMODE_DOLBYDIGITAL, /* Dolby Digital Output (XBOX or PC only). */
+ FSOUND_SPEAKERMODE_HEADPHONES, /* The speakers are headphones. */
+ FSOUND_SPEAKERMODE_MONO, /* The speakers are monaural. */
+ FSOUND_SPEAKERMODE_QUAD, /* The speakers are quadraphonic. */
+ FSOUND_SPEAKERMODE_STEREO, /* The speakers are stereo (default value). */
+ FSOUND_SPEAKERMODE_SURROUND, /* The speakers are surround sound. */
+ FSOUND_SPEAKERMODE_DTS, /* DTS output (XBOX only). */
+ FSOUND_SPEAKERMODE_PROLOGIC2, /* Dolby Prologic 2. Playstation 2 and Gamecube only. PlayStation 2 doesnt support interior panning, but supports 48 voices simultaneously. */
+ FSOUND_SPEAKERMODE_PROLOGIC2_INTERIOR /* Dolby Prologic 2. Playstation 2 and Gamecube only. PlayStation 2 does support interior panning, but only supports 24 voices simultaneously. */
+};
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_INIT_FLAGS
+
+ [DESCRIPTION]
+ Initialization flags. Use them with FSOUND_Init in the flags parameter to change various behaviour.
+
+ FSOUND_INIT_ENABLESYSTEMCHANNELFX Is an init mode which enables the FSOUND mixer buffer to be affected by DirectX 8 effects.
+ Note that due to limitations of DirectSound, FSOUND_Init may fail if this is enabled because the buffersize is too small.
+ This can be fixed with FSOUND_SetBufferSize. Increase the BufferSize until it works.
+ When it is enabled you can use the FSOUND_FX api, and use FSOUND_SYSTEMCHANNEL as the channel id when setting parameters.
+
+ [SEE_ALSO]
+ FSOUND_Init
+]
+*/
+#define FSOUND_INIT_USEDEFAULTMIDISYNTH 0x0001 /* Win32 only - Causes MIDI playback to force software decoding. */
+#define FSOUND_INIT_GLOBALFOCUS 0x0002 /* Win32 only - For DirectSound output - sound is not muted when window is out of focus. */
+#define FSOUND_INIT_ENABLESYSTEMCHANNELFX 0x0004 /* Win32 only - For DirectSound output - Allows FSOUND_FX api to be used on global software mixer output! (use FSOUND_SYSTEMCHANNEL as channel id) */
+#define FSOUND_INIT_ACCURATEVULEVELS 0x0008 /* This latency adjusts FSOUND_GetCurrentLevels, but incurs a small cpu and memory hit */
+#define FSOUND_INIT_PS2_DISABLECORE0REVERB 0x0010 /* PS2 only - Disable reverb on CORE 0 (SPU2 voices 00-23) to regain SRAM */
+#define FSOUND_INIT_PS2_DISABLECORE1REVERB 0x0020 /* PS2 only - Disable reverb on CORE 1 (SPU2 voices 24-47) to regain SRAM */
+#define FSOUND_INIT_PS2_SWAPDMACORES 0x0040 /* PS2 only - By default FMOD uses DMA CH0 for mixing, CH1 for uploads, this flag swaps them around */
+#define FSOUND_INIT_DONTLATENCYADJUST 0x0080 /* Callbacks are not latency adjusted, and are called at mix time. Also information functions are immediate */
+#define FSOUND_INIT_GC_INITLIBS 0x0100 /* GC only - Initializes GC audio libraries */
+#define FSOUND_INIT_STREAM_FROM_MAIN_THREAD 0x0200 /* Turns off fmod streamer thread, and makes streaming update from FSOUND_Update called by the user */
+#define FSOUND_INIT_PS2_USEVOLUMERAMPING 0x0400 /* PS2 only - Turns on volume ramping system to remove hardware clicks. */
+#define FSOUND_INIT_DSOUND_DEFERRED 0x0800 /* Win32 only - For DirectSound output. 3D commands are batched together and executed at FSOUND_Update. */
+#define FSOUND_INIT_DSOUND_HRTF_LIGHT 0x1000 /* Win32 only - For DirectSound output. FSOUND_HW3D buffers use a slightly higher quality algorithm when 3d hardware acceleration is not present. */
+#define FSOUND_INIT_DSOUND_HRTF_FULL 0x2000 /* Win32 only - For DirectSound output. FSOUND_HW3D buffers use full quality 3d playback when 3d hardware acceleration is not present. */
+/* [DEFINE_END] */
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ Status values for internet streams. Use FSOUND_Stream_Net_GetStatus to get the current status of an internet stream.
+
+ [SEE_ALSO]
+ FSOUND_Stream_Net_GetStatus
+]
+*/
+enum FSOUND_STREAM_NET_STATUS
+{
+ FSOUND_STREAM_NET_NOTCONNECTED = 0, /* Stream hasn't connected yet */
+ FSOUND_STREAM_NET_CONNECTING, /* Stream is connecting to remote host */
+ FSOUND_STREAM_NET_BUFFERING, /* Stream is buffering data */
+ FSOUND_STREAM_NET_READY, /* Stream is ready to play */
+ FSOUND_STREAM_NET_ERROR /* Stream has suffered a fatal error */
+};
+
+
+/*
+[ENUM]
+[
+ [DESCRIPTION]
+ Describes the type of a particular tag field.
+
+ [SEE_ALSO]
+ FSOUND_Stream_GetNumTagFields
+ FSOUND_Stream_GetTagField
+ FSOUND_Stream_FindTagField
+]
+*/
+enum FSOUND_TAGFIELD_TYPE
+{
+ FSOUND_TAGFIELD_VORBISCOMMENT = 0, /* A vorbis comment */
+ FSOUND_TAGFIELD_ID3V1, /* Part of an ID3v1 tag */
+ FSOUND_TAGFIELD_ID3V2, /* An ID3v2 frame */
+ FSOUND_TAGFIELD_SHOUTCAST, /* A SHOUTcast header line */
+ FSOUND_TAGFIELD_ICECAST, /* An Icecast header line */
+ FSOUND_TAGFIELD_ASF /* An Advanced Streaming Format header line */
+};
+
+
+/*
+[DEFINE_START]
+[
+ [NAME]
+ FSOUND_STATUS_FLAGS
+
+ [DESCRIPTION]
+ These values describe the protocol and format of an internet stream. Use FSOUND_Stream_Net_GetStatus to retrieve this information for an open internet stream.
+
+ [SEE_ALSO]
+ FSOUND_Stream_Net_GetStatus
+]
+*/
+#define FSOUND_PROTOCOL_SHOUTCAST 0x00000001
+#define FSOUND_PROTOCOL_ICECAST 0x00000002
+#define FSOUND_PROTOCOL_HTTP 0x00000004
+#define FSOUND_FORMAT_MPEG 0x00010000
+#define FSOUND_FORMAT_OGGVORBIS 0x00020000
+/* [DEFINE_END] */
+
+
+/*
+[STRUCTURE]
+[
+ [DESCRIPTION]
+ Structure defining a CD table of contents. This structure is returned as a tag from FSOUND_Stream_FindTagField when the tag name "CD_TOC" is specified.
+ Note: All tracks on the CD - including data tracks- will be represented in this structure so it's use for anything other than generating disc id information is not recommended.
+ See the cdda example program for info on retrieving and using this structure.
+
+ [SEE_ALSO]
+ FSOUND_Stream_Open
+ FSOUND_Stream_FindTagField
+]
+*/
+typedef struct _FSOUND_TOC_TAG
+{
+ char name[4]; /* The string "TOC", just in case this structure is accidentally treated as a string */
+ int numtracks; /* The number of tracks on the CD */
+ int min[100]; /* The start offset of each track in minutes */
+ int sec[100]; /* The start offset of each track in seconds */
+ int frame[100]; /* The start offset of each track in frames */
+
+} FSOUND_TOC_TAG;
+
+
+/* ========================================================================================== */
+/* FUNCTION PROTOTYPES */
+/* ========================================================================================== */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ================================== */
+/* Initialization / Global functions. */
+/* ================================== */
+
+/*
+ PRE - FSOUND_Init functions. These can't be called after FSOUND_Init is
+ called (they will fail). They set up FMOD system functionality.
+*/
+
+DLL_API signed char F_API FSOUND_SetOutput(int outputtype);
+DLL_API signed char F_API FSOUND_SetDriver(int driver);
+DLL_API signed char F_API FSOUND_SetMixer(int mixer);
+DLL_API signed char F_API FSOUND_SetBufferSize(int len_ms);
+DLL_API signed char F_API FSOUND_SetHWND(void *hwnd);
+DLL_API signed char F_API FSOUND_SetMinHardwareChannels(int min);
+DLL_API signed char F_API FSOUND_SetMaxHardwareChannels(int max);
+DLL_API signed char F_API FSOUND_SetMemorySystem(void *pool,
+ int poollen,
+ FSOUND_ALLOCCALLBACK useralloc,
+ FSOUND_REALLOCCALLBACK userrealloc,
+ FSOUND_FREECALLBACK userfree);
+/*
+ Main initialization / closedown functions.
+ Note : Use FSOUND_INIT_USEDEFAULTMIDISYNTH with FSOUND_Init for software override
+ with MIDI playback.
+ : Use FSOUND_INIT_GLOBALFOCUS with FSOUND_Init to make sound audible no matter
+ which window is in focus. (FSOUND_OUTPUT_DSOUND only)
+*/
+
+DLL_API signed char F_API FSOUND_Init(int mixrate, int maxsoftwarechannels, unsigned int flags);
+DLL_API void F_API FSOUND_Close();
+
+/*
+ Runtime system level functions
+*/
+
+DLL_API void F_API FSOUND_Update(); /* This is called to update 3d sound / non-realtime output */
+
+DLL_API void F_API FSOUND_SetSpeakerMode(unsigned int speakermode);
+DLL_API void F_API FSOUND_SetSFXMasterVolume(int volume);
+DLL_API void F_API FSOUND_SetPanSeperation(float pansep);
+DLL_API void F_API FSOUND_File_SetCallbacks(FSOUND_OPENCALLBACK useropen,
+ FSOUND_CLOSECALLBACK userclose,
+ FSOUND_READCALLBACK userread,
+ FSOUND_SEEKCALLBACK userseek,
+ FSOUND_TELLCALLBACK usertell);
+
+/*
+ System information functions.
+*/
+
+DLL_API int F_API FSOUND_GetError();
+DLL_API float F_API FSOUND_GetVersion();
+DLL_API int F_API FSOUND_GetOutput();
+DLL_API void * F_API FSOUND_GetOutputHandle();
+DLL_API int F_API FSOUND_GetDriver();
+DLL_API int F_API FSOUND_GetMixer();
+DLL_API int F_API FSOUND_GetNumDrivers();
+DLL_API const char * F_API FSOUND_GetDriverName(int id);
+DLL_API signed char F_API FSOUND_GetDriverCaps(int id, unsigned int *caps);
+DLL_API int F_API FSOUND_GetOutputRate();
+DLL_API int F_API FSOUND_GetMaxChannels();
+DLL_API int F_API FSOUND_GetMaxSamples();
+DLL_API int F_API FSOUND_GetSFXMasterVolume();
+DLL_API signed char F_API FSOUND_GetNumHWChannels(int *num2d, int *num3d, int *total);
+DLL_API int F_API FSOUND_GetChannelsPlaying();
+DLL_API float F_API FSOUND_GetCPUUsage();
+DLL_API void F_API FSOUND_GetMemoryStats(unsigned int *currentalloced, unsigned int *maxalloced);
+
+/* =================================== */
+/* Sample management / load functions. */
+/* =================================== */
+
+/*
+ Sample creation and management functions
+ Note : Use FSOUND_LOADMEMORY flag with FSOUND_Sample_Load to load from memory.
+ Use FSOUND_LOADRAW flag with FSOUND_Sample_Load to treat as as raw pcm data.
+*/
+
+DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Load(int index, const char *name_or_data, unsigned int mode, int offset, int length);
+DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Alloc(int index, int length, unsigned int mode, int deffreq, int defvol, int defpan, int defpri);
+DLL_API void F_API FSOUND_Sample_Free(FSOUND_SAMPLE *sptr);
+DLL_API signed char F_API FSOUND_Sample_Upload(FSOUND_SAMPLE *sptr, void *srcdata, unsigned int mode);
+DLL_API signed char F_API FSOUND_Sample_Lock(FSOUND_SAMPLE *sptr, int offset, int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
+DLL_API signed char F_API FSOUND_Sample_Unlock(FSOUND_SAMPLE *sptr, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
+
+/*
+ Sample control functions
+*/
+
+DLL_API signed char F_API FSOUND_Sample_SetMode(FSOUND_SAMPLE *sptr, unsigned int mode);
+DLL_API signed char F_API FSOUND_Sample_SetLoopPoints(FSOUND_SAMPLE *sptr, int loopstart, int loopend);
+DLL_API signed char F_API FSOUND_Sample_SetDefaults(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri);
+DLL_API signed char F_API FSOUND_Sample_SetDefaultsEx(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri, int varfreq, int varvol, int varpan);
+DLL_API signed char F_API FSOUND_Sample_SetMinMaxDistance(FSOUND_SAMPLE *sptr, float min, float max);
+DLL_API signed char F_API FSOUND_Sample_SetMaxPlaybacks(FSOUND_SAMPLE *sptr, int max);
+
+/*
+ Sample information functions
+*/
+
+DLL_API FSOUND_SAMPLE * F_API FSOUND_Sample_Get(int sampno);
+DLL_API const char * F_API FSOUND_Sample_GetName(FSOUND_SAMPLE *sptr);
+DLL_API unsigned int F_API FSOUND_Sample_GetLength(FSOUND_SAMPLE *sptr);
+DLL_API signed char F_API FSOUND_Sample_GetLoopPoints(FSOUND_SAMPLE *sptr, int *loopstart, int *loopend);
+DLL_API signed char F_API FSOUND_Sample_GetDefaults(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri);
+DLL_API signed char F_API FSOUND_Sample_GetDefaultsEx(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri, int *varfreq, int *varvol, int *varpan);
+DLL_API unsigned int F_API FSOUND_Sample_GetMode(FSOUND_SAMPLE *sptr);
+DLL_API signed char F_API FSOUND_Sample_GetMinMaxDistance(FSOUND_SAMPLE *sptr, float *min, float *max);
+
+/* ============================ */
+/* Channel control functions. */
+/* ============================ */
+
+/*
+ Playing and stopping sounds.
+ Note : Use FSOUND_FREE as the 'channel' variable, to let FMOD pick a free channel for you.
+ Use FSOUND_ALL as the 'channel' variable to control ALL channels with one function call!
+*/
+
+DLL_API int F_API FSOUND_PlaySound(int channel, FSOUND_SAMPLE *sptr);
+DLL_API int F_API FSOUND_PlaySoundEx(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+DLL_API signed char F_API FSOUND_StopSound(int channel);
+
+/*
+ Functions to control playback of a channel.
+ Note : FSOUND_ALL can be used on most of these functions as a channel value.
+*/
+
+DLL_API signed char F_API FSOUND_SetFrequency(int channel, int freq);
+DLL_API signed char F_API FSOUND_SetVolume(int channel, int vol);
+DLL_API signed char F_API FSOUND_SetVolumeAbsolute(int channel, int vol);
+DLL_API signed char F_API FSOUND_SetPan(int channel, int pan);
+DLL_API signed char F_API FSOUND_SetSurround(int channel, signed char surround);
+DLL_API signed char F_API FSOUND_SetMute(int channel, signed char mute);
+DLL_API signed char F_API FSOUND_SetPriority(int channel, int priority);
+DLL_API signed char F_API FSOUND_SetReserved(int channel, signed char reserved);
+DLL_API signed char F_API FSOUND_SetPaused(int channel, signed char paused);
+DLL_API signed char F_API FSOUND_SetLoopMode(int channel, unsigned int loopmode);
+DLL_API signed char F_API FSOUND_SetCurrentPosition(int channel, unsigned int offset);
+DLL_API signed char F_API FSOUND_3D_SetAttributes(int channel, const float *pos, const float *vel);
+DLL_API signed char F_API FSOUND_3D_SetMinMaxDistance(int channel, float min, float max);
+
+/*
+ Channel information functions.
+*/
+
+DLL_API signed char F_API FSOUND_IsPlaying(int channel);
+DLL_API int F_API FSOUND_GetFrequency(int channel);
+DLL_API int F_API FSOUND_GetVolume(int channel);
+DLL_API int F_API FSOUND_GetAmplitude(int channel);
+DLL_API int F_API FSOUND_GetPan(int channel);
+DLL_API signed char F_API FSOUND_GetSurround(int channel);
+DLL_API signed char F_API FSOUND_GetMute(int channel);
+DLL_API int F_API FSOUND_GetPriority(int channel);
+DLL_API signed char F_API FSOUND_GetReserved(int channel);
+DLL_API signed char F_API FSOUND_GetPaused(int channel);
+DLL_API unsigned int F_API FSOUND_GetLoopMode(int channel);
+DLL_API unsigned int F_API FSOUND_GetCurrentPosition(int channel);
+DLL_API FSOUND_SAMPLE * F_API FSOUND_GetCurrentSample(int channel);
+DLL_API signed char F_API FSOUND_GetCurrentLevels(int channel, float *l, float *r);
+DLL_API int F_API FSOUND_GetNumSubChannels(int channel);
+DLL_API int F_API FSOUND_GetSubChannel(int channel, int subchannel);
+DLL_API signed char F_API FSOUND_3D_GetAttributes(int channel, float *pos, float *vel);
+DLL_API signed char F_API FSOUND_3D_GetMinMaxDistance(int channel, float *min, float *max);
+
+/* ========================== */
+/* Global 3D sound functions. */
+/* ========================== */
+
+/*
+ See also 3d sample and channel based functions above.
+ Call FSOUND_Update once a frame to process 3d information.
+*/
+
+DLL_API void F_API FSOUND_3D_Listener_SetAttributes(const float *pos, const float *vel, float fx, float fy, float fz, float tx, float ty, float tz);
+DLL_API void F_API FSOUND_3D_Listener_GetAttributes(float *pos, float *vel, float *fx, float *fy, float *fz, float *tx, float *ty, float *tz);
+DLL_API void F_API FSOUND_3D_Listener_SetCurrent(int current, int numlisteners); /* use this if you use multiple listeners / splitscreen */
+DLL_API void F_API FSOUND_3D_SetDopplerFactor(float scale);
+DLL_API void F_API FSOUND_3D_SetDistanceFactor(float scale);
+DLL_API void F_API FSOUND_3D_SetRolloffFactor(float scale);
+
+/* =================== */
+/* FX functions. */
+/* =================== */
+
+/*
+ Functions to control DX8 only effects processing.
+
+ - FX enabled samples can only be played once at a time, not multiple times at once.
+ - Sounds have to be created with FSOUND_HW2D or FSOUND_HW3D for this to work.
+ - FSOUND_INIT_ENABLESYSTEMCHANNELFX can be used to apply hardware effect processing to the
+ global mixed output of FMOD's software channels.
+ - FSOUND_FX_Enable returns an FX handle that you can use to alter fx parameters.
+ - FSOUND_FX_Enable can be called multiple times in a row, even on the same FX type,
+ it will return a unique handle for each FX.
+ - FSOUND_FX_Enable cannot be called if the sound is playing or locked.
+ - FSOUND_FX_Disable must be called to reset/clear the FX from a channel.
+*/
+
+DLL_API int F_API FSOUND_FX_Enable(int channel, unsigned int fxtype); /* See FSOUND_FX_MODES */
+DLL_API signed char F_API FSOUND_FX_Disable(int channel); /* Disables all effects */
+
+DLL_API signed char F_API FSOUND_FX_SetChorus(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
+DLL_API signed char F_API FSOUND_FX_SetCompressor(int fxid, float Gain, float Attack, float Release, float Threshold, float Ratio, float Predelay);
+DLL_API signed char F_API FSOUND_FX_SetDistortion(int fxid, float Gain, float Edge, float PostEQCenterFrequency, float PostEQBandwidth, float PreLowpassCutoff);
+DLL_API signed char F_API FSOUND_FX_SetEcho(int fxid, float WetDryMix, float Feedback, float LeftDelay, float RightDelay, int PanDelay);
+DLL_API signed char F_API FSOUND_FX_SetFlanger(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
+DLL_API signed char F_API FSOUND_FX_SetGargle(int fxid, int RateHz, int WaveShape);
+DLL_API signed char F_API FSOUND_FX_SetI3DL2Reverb(int fxid, int Room, int RoomHF, float RoomRolloffFactor, float DecayTime, float DecayHFRatio, int Reflections, float ReflectionsDelay, int Reverb, float ReverbDelay, float Diffusion, float Density, float HFReference);
+DLL_API signed char F_API FSOUND_FX_SetParamEQ(int fxid, float Center, float Bandwidth, float Gain);
+DLL_API signed char F_API FSOUND_FX_SetWavesReverb(int fxid, float InGain, float ReverbMix, float ReverbTime, float HighFreqRTRatio);
+
+/* ========================= */
+/* File Streaming functions. */
+/* ========================= */
+
+/*
+ Note : Use FSOUND_LOADMEMORY flag with FSOUND_Stream_Open to stream from memory.
+ Use FSOUND_LOADRAW flag with FSOUND_Stream_Open to treat stream as raw pcm data.
+ Use FSOUND_MPEGACCURATE flag with FSOUND_Stream_Open to open mpegs in 'accurate mode' for settime/gettime/getlengthms.
+ Use FSOUND_FREE as the 'channel' variable, to let FMOD pick a free channel for you.
+*/
+
+DLL_API signed char F_API FSOUND_Stream_SetBufferSize(int ms); /* call this before opening streams, not after */
+
+DLL_API FSOUND_STREAM * F_API FSOUND_Stream_Open(const char *name_or_data, unsigned int mode, int offset, int length);
+DLL_API FSOUND_STREAM * F_API FSOUND_Stream_Create(FSOUND_STREAMCALLBACK callback, int length, unsigned int mode, int samplerate, void *userdata);
+DLL_API signed char F_API FSOUND_Stream_Close(FSOUND_STREAM *stream);
+
+DLL_API int F_API FSOUND_Stream_Play(int channel, FSOUND_STREAM *stream);
+DLL_API int F_API FSOUND_Stream_PlayEx(int channel, FSOUND_STREAM *stream, FSOUND_DSPUNIT *dsp, signed char startpaused);
+DLL_API signed char F_API FSOUND_Stream_Stop(FSOUND_STREAM *stream);
+
+DLL_API signed char F_API FSOUND_Stream_SetPosition(FSOUND_STREAM *stream, unsigned int position);
+DLL_API unsigned int F_API FSOUND_Stream_GetPosition(FSOUND_STREAM *stream);
+DLL_API signed char F_API FSOUND_Stream_SetTime(FSOUND_STREAM *stream, int ms);
+DLL_API int F_API FSOUND_Stream_GetTime(FSOUND_STREAM *stream);
+DLL_API int F_API FSOUND_Stream_GetLength(FSOUND_STREAM *stream);
+DLL_API int F_API FSOUND_Stream_GetLengthMs(FSOUND_STREAM *stream);
+
+DLL_API signed char F_API FSOUND_Stream_SetMode(FSOUND_STREAM *stream, unsigned int mode);
+DLL_API unsigned int F_API FSOUND_Stream_GetMode(FSOUND_STREAM *stream);
+DLL_API signed char F_API FSOUND_Stream_SetLoopPoints(FSOUND_STREAM *stream, unsigned int loopstartpcm, unsigned int loopendpcm);
+DLL_API signed char F_API FSOUND_Stream_SetLoopCount(FSOUND_STREAM *stream, int count);
+DLL_API int F_API FSOUND_Stream_GetOpenState(FSOUND_STREAM *stream); /* use with FSOUND_NONBLOCKING opened streams */
+DLL_API FSOUND_SAMPLE * F_API FSOUND_Stream_GetSample(FSOUND_STREAM *stream);
+DLL_API FSOUND_DSPUNIT * F_API FSOUND_Stream_CreateDSP(FSOUND_STREAM *stream, FSOUND_DSPCALLBACK callback, int priority, void *userdata);
+
+DLL_API signed char F_API FSOUND_Stream_SetEndCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, void *userdata);
+DLL_API signed char F_API FSOUND_Stream_SetSyncCallback(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, void *userdata);
+
+DLL_API FSOUND_SYNCPOINT * F_API FSOUND_Stream_AddSyncPoint(FSOUND_STREAM *stream, unsigned int pcmoffset, const char *name);
+DLL_API signed char F_API FSOUND_Stream_DeleteSyncPoint(FSOUND_SYNCPOINT *point);
+DLL_API int F_API FSOUND_Stream_GetNumSyncPoints(FSOUND_STREAM *stream);
+DLL_API FSOUND_SYNCPOINT * F_API FSOUND_Stream_GetSyncPoint(FSOUND_STREAM *stream, int index);
+DLL_API char * F_API FSOUND_Stream_GetSyncPointInfo(FSOUND_SYNCPOINT *point, unsigned int *pcmoffset);
+
+DLL_API signed char F_API FSOUND_Stream_SetSubStream(FSOUND_STREAM *stream, int index); /* For FMOD .FSB bank files. */
+DLL_API int F_API FSOUND_Stream_GetNumSubStreams(FSOUND_STREAM *stream); /* For FMOD .FSB bank files. */
+DLL_API signed char F_API FSOUND_Stream_SetSubStreamSentence(FSOUND_STREAM *stream, const int *sentencelist, int numitems);
+
+DLL_API signed char F_API FSOUND_Stream_GetNumTagFields(FSOUND_STREAM *stream, int *num);
+DLL_API signed char F_API FSOUND_Stream_GetTagField(FSOUND_STREAM *stream, int num, int *type, char **name, void **value, int *length);
+DLL_API signed char F_API FSOUND_Stream_FindTagField(FSOUND_STREAM *stream, int type, const char *name, void **value, int *length);
+
+/*
+ Internet streaming functions
+*/
+
+DLL_API signed char F_API FSOUND_Stream_Net_SetProxy(const char *proxy);
+DLL_API char * F_API FSOUND_Stream_Net_GetLastServerStatus();
+DLL_API signed char F_API FSOUND_Stream_Net_SetBufferProperties(int buffersize, int prebuffer_percent, int rebuffer_percent);
+DLL_API signed char F_API FSOUND_Stream_Net_GetBufferProperties(int *buffersize, int *prebuffer_percent, int *rebuffer_percent);
+DLL_API signed char F_API FSOUND_Stream_Net_SetMetadataCallback(FSOUND_STREAM *stream, FSOUND_METADATACALLBACK callback, void *userdata);
+DLL_API signed char F_API FSOUND_Stream_Net_GetStatus(FSOUND_STREAM *stream, int *status, int *bufferpercentused, int *bitrate, unsigned int *flags);
+
+/* =================== */
+/* CD audio functions. */
+/* =================== */
+
+/*
+ Note : 0 = default cdrom. Otherwise specify the drive letter, for example. 'D'.
+*/
+
+DLL_API signed char F_API FSOUND_CD_Play(char drive, int track);
+DLL_API void F_API FSOUND_CD_SetPlayMode(char drive, signed char mode);
+DLL_API signed char F_API FSOUND_CD_Stop(char drive);
+DLL_API signed char F_API FSOUND_CD_SetPaused(char drive, signed char paused);
+DLL_API signed char F_API FSOUND_CD_SetVolume(char drive, int volume);
+DLL_API signed char F_API FSOUND_CD_SetTrackTime(char drive, unsigned int ms);
+DLL_API signed char F_API FSOUND_CD_OpenTray(char drive, signed char open);
+
+DLL_API signed char F_API FSOUND_CD_GetPaused(char drive);
+DLL_API int F_API FSOUND_CD_GetTrack(char drive);
+DLL_API int F_API FSOUND_CD_GetNumTracks(char drive);
+DLL_API int F_API FSOUND_CD_GetVolume(char drive);
+DLL_API int F_API FSOUND_CD_GetTrackLength(char drive, int track);
+DLL_API int F_API FSOUND_CD_GetTrackTime(char drive);
+
+/* ============== */
+/* DSP functions. */
+/* ============== */
+
+/*
+ DSP Unit control and information functions.
+ These functions allow you access to the mixed stream that FMOD uses to play back sound on.
+*/
+
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_Create(FSOUND_DSPCALLBACK callback, int priority, void *userdata);
+DLL_API void F_API FSOUND_DSP_Free(FSOUND_DSPUNIT *unit);
+DLL_API void F_API FSOUND_DSP_SetPriority(FSOUND_DSPUNIT *unit, int priority);
+DLL_API int F_API FSOUND_DSP_GetPriority(FSOUND_DSPUNIT *unit);
+DLL_API void F_API FSOUND_DSP_SetActive(FSOUND_DSPUNIT *unit, signed char active);
+DLL_API signed char F_API FSOUND_DSP_GetActive(FSOUND_DSPUNIT *unit);
+
+/*
+ Functions to get hold of FSOUND 'system DSP unit' handles.
+*/
+
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClearUnit();
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetSFXUnit();
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetMusicUnit();
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetFFTUnit();
+DLL_API FSOUND_DSPUNIT *F_API FSOUND_DSP_GetClipAndCopyUnit();
+
+/*
+ Miscellaneous DSP functions
+ Note for the spectrum analysis function to work, you have to enable the FFT DSP unit with
+ the following code FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), TRUE);
+ It is off by default to save cpu usage.
+*/
+
+DLL_API signed char F_API FSOUND_DSP_MixBuffers(void *destbuffer, void *srcbuffer, int len, int freq, int vol, int pan, unsigned int mode);
+DLL_API void F_API FSOUND_DSP_ClearMixBuffer();
+DLL_API int F_API FSOUND_DSP_GetBufferLength(); /* Length of each DSP update */
+DLL_API int F_API FSOUND_DSP_GetBufferLengthTotal(); /* Total buffer length due to FSOUND_SetBufferSize */
+DLL_API float * F_API FSOUND_DSP_GetSpectrum(); /* Array of 512 floats - call FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), TRUE)) for this to work. */
+
+/* =================================================================================== */
+/* Reverb functions. (eax2/eax3 reverb) (ONLY SUPPORTED ON WIN32 W/ FSOUND_HW3D FLAG) */
+/* =================================================================================== */
+
+/*
+ See top of file for definitions and information on the reverb parameters.
+*/
+
+DLL_API signed char F_API FSOUND_Reverb_SetProperties(const FSOUND_REVERB_PROPERTIES *prop);
+DLL_API signed char F_API FSOUND_Reverb_GetProperties(FSOUND_REVERB_PROPERTIES *prop);
+DLL_API signed char F_API FSOUND_Reverb_SetChannelProperties(int channel, const FSOUND_REVERB_CHANNELPROPERTIES *prop);
+DLL_API signed char F_API FSOUND_Reverb_GetChannelProperties(int channel, FSOUND_REVERB_CHANNELPROPERTIES *prop);
+
+/* ===================================================== */
+/* Recording functions (ONLY SUPPORTED IN WIN32, WINCE) */
+/* ===================================================== */
+
+/*
+ Recording initialization functions
+*/
+
+DLL_API signed char F_API FSOUND_Record_SetDriver(int outputtype);
+DLL_API int F_API FSOUND_Record_GetNumDrivers();
+DLL_API const char * F_API FSOUND_Record_GetDriverName(int id);
+DLL_API int F_API FSOUND_Record_GetDriver();
+
+/*
+ Recording functionality. Only one recording session will work at a time.
+*/
+
+DLL_API signed char F_API FSOUND_Record_StartSample(FSOUND_SAMPLE *sptr, signed char loop);
+DLL_API signed char F_API FSOUND_Record_Stop();
+DLL_API int F_API FSOUND_Record_GetPosition();
+
+/* ========================================================================================== */
+/* FMUSIC API (MOD,S3M,XM,IT,MIDI PLAYBACK) */
+/* ========================================================================================== */
+
+/*
+ Song management / playback functions.
+*/
+
+DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSong(const char *name);
+DLL_API FMUSIC_MODULE * F_API FMUSIC_LoadSongEx(const char *name_or_data, int offset, int length, unsigned int mode, const int *samplelist, int samplelistnum);
+DLL_API int F_API FMUSIC_GetOpenState(FMUSIC_MODULE *mod);
+DLL_API signed char F_API FMUSIC_FreeSong(FMUSIC_MODULE *mod);
+DLL_API signed char F_API FMUSIC_PlaySong(FMUSIC_MODULE *mod);
+DLL_API signed char F_API FMUSIC_StopSong(FMUSIC_MODULE *mod);
+DLL_API void F_API FMUSIC_StopAllSongs();
+
+DLL_API signed char F_API FMUSIC_SetZxxCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback);
+DLL_API signed char F_API FMUSIC_SetRowCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int rowstep);
+DLL_API signed char F_API FMUSIC_SetOrderCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int orderstep);
+DLL_API signed char F_API FMUSIC_SetInstCallback(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int instrument);
+
+DLL_API signed char F_API FMUSIC_SetSample(FMUSIC_MODULE *mod, int sampno, FSOUND_SAMPLE *sptr);
+DLL_API signed char F_API FMUSIC_SetUserData(FMUSIC_MODULE *mod, void *userdata);
+DLL_API signed char F_API FMUSIC_OptimizeChannels(FMUSIC_MODULE *mod, int maxchannels, int minvolume);
+
+/*
+ Runtime song functions.
+*/
+
+DLL_API signed char F_API FMUSIC_SetReverb(signed char reverb); /* MIDI only */
+DLL_API signed char F_API FMUSIC_SetLooping(FMUSIC_MODULE *mod, signed char looping);
+DLL_API signed char F_API FMUSIC_SetOrder(FMUSIC_MODULE *mod, int order);
+DLL_API signed char F_API FMUSIC_SetPaused(FMUSIC_MODULE *mod, signed char pause);
+DLL_API signed char F_API FMUSIC_SetMasterVolume(FMUSIC_MODULE *mod, int volume);
+DLL_API signed char F_API FMUSIC_SetMasterSpeed(FMUSIC_MODULE *mode, float speed);
+DLL_API signed char F_API FMUSIC_SetPanSeperation(FMUSIC_MODULE *mod, float pansep);
+
+/*
+ Static song information functions.
+*/
+
+DLL_API const char * F_API FMUSIC_GetName(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetType(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetNumOrders(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetNumPatterns(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetNumInstruments(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetNumSamples(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetNumChannels(FMUSIC_MODULE *mod);
+DLL_API FSOUND_SAMPLE * F_API FMUSIC_GetSample(FMUSIC_MODULE *mod, int sampno);
+DLL_API int F_API FMUSIC_GetPatternLength(FMUSIC_MODULE *mod, int orderno);
+
+/*
+ Runtime song information.
+*/
+
+DLL_API signed char F_API FMUSIC_IsFinished(FMUSIC_MODULE *mod);
+DLL_API signed char F_API FMUSIC_IsPlaying(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetMasterVolume(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetGlobalVolume(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetOrder(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetPattern(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetSpeed(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetBPM(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetRow(FMUSIC_MODULE *mod);
+DLL_API signed char F_API FMUSIC_GetPaused(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetTime(FMUSIC_MODULE *mod);
+DLL_API int F_API FMUSIC_GetRealChannel(FMUSIC_MODULE *mod, int modchannel);
+DLL_API void * F_API FMUSIC_GetUserData(FMUSIC_MODULE *mod);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* =========================================================================================== */
+/* FMOD Dynamic DLL loading header. Copyright (c), Firelight Technologies Pty, Ltd. 1999-2004. */
+/* =========================================================================================== */
+
+#ifndef _FMODDYN_H_
+#define _FMODDYN_H_
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+ #include <windows.h>
+#else
+ #include <dlfcn.h>
+ #include <string.h>
+#endif
+#include <stdlib.h>
+
+#include "fmod.h"
+
+typedef struct
+{
+ void *module;
+
+ signed char (F_API *FSOUND_SetOutput)(int outputtype);
+ signed char (F_API *FSOUND_SetDriver)(int driver);
+ signed char (F_API *FSOUND_SetMixer)(int mixer);
+ signed char (F_API *FSOUND_SetBufferSize)(int len_ms);
+ signed char (F_API *FSOUND_SetHWND)(void *hwnd);
+ signed char (F_API *FSOUND_SetMinHardwareChannels)(int min);
+ signed char (F_API *FSOUND_SetMaxHardwareChannels)(int max);
+ signed char (F_API *FSOUND_SetMemorySystem)(void *pool, int poollen, FSOUND_ALLOCCALLBACK useralloc, FSOUND_REALLOCCALLBACK userrealloc, FSOUND_FREECALLBACK userfree);
+ signed char (F_API *FSOUND_Init)(int mixrate, int maxsoftwarechannels, unsigned int flags);
+ void (F_API *FSOUND_Close)();
+ void (F_API *FSOUND_Update)(); /* you must call this once a frame */
+ void (F_API *FSOUND_SetSpeakerMode)(unsigned int speakermode);
+ void (F_API *FSOUND_SetSFXMasterVolume)(int volume);
+ void (F_API *FSOUND_SetPanSeperation)(float pansep);
+ void (F_API *FSOUND_File_SetCallbacks)(FSOUND_OPENCALLBACK useropen, FSOUND_CLOSECALLBACK userclose, FSOUND_READCALLBACK userread, FSOUND_SEEKCALLBACK userseek, FSOUND_TELLCALLBACK usertell);
+ int (F_API *FSOUND_GetError)();
+ float (F_API *FSOUND_GetVersion)();
+ int (F_API *FSOUND_GetOutput)();
+ void * (F_API *FSOUND_GetOutputHandle)();
+ int (F_API *FSOUND_GetDriver)();
+ int (F_API *FSOUND_GetMixer)();
+ int (F_API *FSOUND_GetNumDrivers)();
+ signed char * (F_API *FSOUND_GetDriverName)(int id);
+ signed char (F_API *FSOUND_GetDriverCaps)(int id, unsigned int *caps);
+ int (F_API *FSOUND_GetOutputRate)();
+ int (F_API *FSOUND_GetMaxChannels)();
+ int (F_API *FSOUND_GetMaxSamples)();
+ int (F_API *FSOUND_GetSFXMasterVolume)();
+ signed char (F_API *FSOUND_GetNumHWChannels)(int *num2d, int *num3d, int *total);
+ int (F_API *FSOUND_GetChannelsPlaying)();
+ float (F_API *FSOUND_GetCPUUsage)();
+ void (F_API *FSOUND_GetMemoryStats)(unsigned int *currentalloced, unsigned int *maxalloced);
+ FSOUND_SAMPLE * (F_API *FSOUND_Sample_Load)(int index, const char *name_or_data, unsigned int mode, int offset, int length);
+ FSOUND_SAMPLE * (F_API *FSOUND_Sample_Alloc)(int index, int length, unsigned int mode, int deffreq, int defvol, int defpan, int defpri);
+ void (F_API *FSOUND_Sample_Free)(FSOUND_SAMPLE *sptr);
+ signed char (F_API *FSOUND_Sample_Upload)(FSOUND_SAMPLE *sptr, void *srcdata, unsigned int mode);
+ signed char (F_API *FSOUND_Sample_Lock)(FSOUND_SAMPLE *sptr, int offset, int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
+ signed char (F_API *FSOUND_Sample_Unlock)(FSOUND_SAMPLE *sptr, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
+ signed char (F_API *FSOUND_Sample_SetMode)(FSOUND_SAMPLE *sptr, unsigned int mode);
+ signed char (F_API *FSOUND_Sample_SetLoopPoints)(FSOUND_SAMPLE *sptr, int loopstart, int loopend);
+ signed char (F_API *FSOUND_Sample_SetDefaults)(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri);
+ signed char (F_API *FSOUND_Sample_SetDefaultsEx)(FSOUND_SAMPLE *sptr, int deffreq, int defvol, int defpan, int defpri, int varfreq, int varvol, int varpan);
+ signed char (F_API *FSOUND_Sample_SetMinMaxDistance)(FSOUND_SAMPLE *sptr, float min, float max);
+ signed char (F_API *FSOUND_Sample_SetMaxPlaybacks)(FSOUND_SAMPLE *sptr, int max);
+ FSOUND_SAMPLE * (F_API *FSOUND_Sample_Get)(int sampno);
+ char * (F_API *FSOUND_Sample_GetName)(FSOUND_SAMPLE *sptr);
+ unsigned int (F_API *FSOUND_Sample_GetLength)(FSOUND_SAMPLE *sptr);
+ signed char (F_API *FSOUND_Sample_GetLoopPoints)(FSOUND_SAMPLE *sptr, int *loopstart, int *loopend);
+ signed char (F_API *FSOUND_Sample_GetDefaults)(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri);
+ signed char (F_API *FSOUND_Sample_GetDefaultsEx)(FSOUND_SAMPLE *sptr, int *deffreq, int *defvol, int *defpan, int *defpri, int *varfreq, int *varvol, int *varpan);
+ unsigned int (F_API *FSOUND_Sample_GetMode)(FSOUND_SAMPLE *sptr);
+ signed char (F_API *FSOUND_Sample_GetMinMaxDistance)(FSOUND_SAMPLE *sptr, float *min, float *max);
+ int (F_API *FSOUND_PlaySound)(int channel, FSOUND_SAMPLE *sptr);
+ int (F_API *FSOUND_PlaySoundEx)(int channel, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused);
+ signed char (F_API *FSOUND_StopSound)(int channel);
+ signed char (F_API *FSOUND_SetFrequency)(int channel, int freq);
+ signed char (F_API *FSOUND_SetVolume)(int channel, int vol);
+ signed char (F_API *FSOUND_SetVolumeAbsolute)(int channel, int vol);
+ signed char (F_API *FSOUND_SetPan)(int channel, int pan);
+ signed char (F_API *FSOUND_SetSurround)(int channel, signed char surround);
+ signed char (F_API *FSOUND_SetMute)(int channel, signed char mute);
+ signed char (F_API *FSOUND_SetPriority)(int channel, int priority);
+ signed char (F_API *FSOUND_SetReserved)(int channel, signed char reserved);
+ signed char (F_API *FSOUND_SetPaused)(int channel, signed char paused);
+ signed char (F_API *FSOUND_SetLoopMode)(int channel, unsigned int loopmode);
+ signed char (F_API *FSOUND_SetCurrentPosition)(int channel, unsigned int offset);
+ signed char (F_API *FSOUND_3D_SetAttributes)(int channel, float *pos, float *vel);
+ signed char (F_API *FSOUND_3D_SetMinMaxDistance)(int channel, float min, float max);
+ signed char (F_API *FSOUND_IsPlaying)(int channel);
+ int (F_API *FSOUND_GetFrequency)(int channel);
+ int (F_API *FSOUND_GetVolume)(int channel);
+ int (F_API *FSOUND_GetAmplitude)(int channel);
+ int (F_API *FSOUND_GetPan)(int channel);
+ signed char (F_API *FSOUND_GetSurround)(int channel);
+ signed char (F_API *FSOUND_GetMute)(int channel);
+ int (F_API *FSOUND_GetPriority)(int channel);
+ signed char (F_API *FSOUND_GetReserved)(int channel);
+ signed char (F_API *FSOUND_GetPaused)(int channel);
+ unsigned int (F_API *FSOUND_GetLoopMode)(int channel);
+ unsigned int (F_API *FSOUND_GetCurrentPosition)(int channel);
+ FSOUND_SAMPLE * (F_API *FSOUND_GetCurrentSample)(int channel);
+ signed char (F_API *FSOUND_GetCurrentLevels)(int channel, float *l, float *r);
+ int (F_API *FSOUND_GetNumSubChannels)(int channel);
+ int (F_API *FSOUND_GetSubChannel)(int channel, int subchannel);
+ signed char (F_API *FSOUND_3D_GetAttributes)(int channel, float *pos, float *vel);
+ signed char (F_API *FSOUND_3D_GetMinMaxDistance)(int channel, float *min, float *max);
+ void (F_API *FSOUND_3D_SetDopplerFactor)(float scale);
+ void (F_API *FSOUND_3D_SetDistanceFactor)(float scale);
+ void (F_API *FSOUND_3D_SetRolloffFactor)(float scale);
+ void (F_API *FSOUND_3D_Listener_SetCurrent)(int current, int numlisteners); /* use this if you use multiple listeners / splitscreen */
+ void (F_API *FSOUND_3D_Listener_SetAttributes)(float *pos, float *vel, float fx, float fy, float fz, float tx, float ty, float tz);
+ void (F_API *FSOUND_3D_Listener_GetAttributes)(float *pos, float *vel, float *fx, float *fy, float *fz, float *tx, float *ty, float *tz);
+ int (F_API *FSOUND_FX_Enable)(int channel, unsigned int fx); /* See FSOUND_FX_MODES */
+ signed char (F_API *FSOUND_FX_Disable)(int channel);
+ signed char (F_API *FSOUND_FX_SetChorus)(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
+ signed char (F_API *FSOUND_FX_SetCompressor)(int fxid, float Gain, float Attack, float Release, float Threshold, float Ratio, float Predelay);
+ signed char (F_API *FSOUND_FX_SetDistortion)(int fxid, float Gain, float Edge, float PostEQCenterFrequency, float PostEQBandwidth, float PreLowpassCutoff);
+ signed char (F_API *FSOUND_FX_SetEcho)(int fxid, float WetDryMix, float Feedback, float LeftDelay, float RightDelay, int PanDelay);
+ signed char (F_API *FSOUND_FX_SetFlanger)(int fxid, float WetDryMix, float Depth, float Feedback, float Frequency, int Waveform, float Delay, int Phase);
+ signed char (F_API *FSOUND_FX_SetGargle)(int fxid, int RateHz, int WaveShape);
+ signed char (F_API *FSOUND_FX_SetI3DL2Reverb)(int fxid, int Room, int RoomHF, float RoomRolloffFactor, float DecayTime, float DecayHFRatio, int Reflections, float ReflectionsDelay, int Reverb, float ReverbDelay, float Diffusion, float Density, float HFReference);
+ signed char (F_API *FSOUND_FX_SetParamEQ)(int fxid, float Center, float Bandwidth, float Gain);
+ signed char (F_API *FSOUND_FX_SetWavesReverb)(int fxid, float InGain, float ReverbMix, float ReverbTime, float HighFreqRTRatio);
+ signed char (F_API *FSOUND_Stream_SetBufferSize)(int ms); /* call this before opening streams, not after */
+ FSOUND_STREAM * (F_API *FSOUND_Stream_Open)(const char *name_or_data, unsigned int mode, int offset, int length);
+ FSOUND_STREAM * (F_API *FSOUND_Stream_Create)(FSOUND_STREAMCALLBACK callback, int length, unsigned int mode, int samplerate, void *userdata);
+ signed char (F_API *FSOUND_Stream_Close)(FSOUND_STREAM *stream);
+ int (F_API *FSOUND_Stream_Play)(int channel, FSOUND_STREAM *stream);
+ int (F_API *FSOUND_Stream_PlayEx)(int channel, FSOUND_STREAM *stream, FSOUND_DSPUNIT *dsp, signed char startpaused);
+ signed char (F_API *FSOUND_Stream_Stop)(FSOUND_STREAM *stream);
+ signed char (F_API *FSOUND_Stream_SetPosition)(FSOUND_STREAM *stream, unsigned int position);
+ unsigned int (F_API *FSOUND_Stream_GetPosition)(FSOUND_STREAM *stream);
+ signed char (F_API *FSOUND_Stream_SetTime)(FSOUND_STREAM *stream, int ms);
+ int (F_API *FSOUND_Stream_GetTime)(FSOUND_STREAM *stream);
+ int (F_API *FSOUND_Stream_GetLength)(FSOUND_STREAM *stream);
+ int (F_API *FSOUND_Stream_GetLengthMs)(FSOUND_STREAM *stream);
+ signed char (F_API *FSOUND_Stream_SetMode)(FSOUND_STREAM *stream, unsigned int mode);
+ unsigned int (F_API *FSOUND_Stream_GetMode)(FSOUND_STREAM *stream);
+ signed char (F_API *FSOUND_Stream_SetLoopPoints)(FSOUND_STREAM *stream, unsigned int loopstartpcm, unsigned int loopendpcm);
+ signed char (F_API *FSOUND_Stream_SetLoopCount)(FSOUND_STREAM *stream, int count);
+ int (F_API *FSOUND_Stream_GetOpenState)(FSOUND_STREAM *stream);
+ FSOUND_SAMPLE * (F_API *FSOUND_Stream_GetSample)(FSOUND_STREAM *stream); /* every stream contains a sample to playback on */
+ FSOUND_DSPUNIT * (F_API *FSOUND_Stream_CreateDSP)(FSOUND_STREAM *stream, FSOUND_DSPCALLBACK callback, int priority, void *userdata);
+ signed char (F_API *FSOUND_Stream_SetEndCallback)(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, void *userdata);
+ signed char (F_API *FSOUND_Stream_SetSyncCallback)(FSOUND_STREAM *stream, FSOUND_STREAMCALLBACK callback, void *userdata);
+ FSOUND_SYNCPOINT *(F_API *FSOUND_Stream_AddSyncPoint)(FSOUND_STREAM *stream, unsigned int pcmoffset, void *userdata);
+ signed char (F_API *FSOUND_Stream_DeleteSyncPoint)(FSOUND_SYNCPOINT *point);
+ int (F_API *FSOUND_Stream_GetNumSyncPoints)(FSOUND_STREAM *stream);
+ FSOUND_SYNCPOINT *(F_API *FSOUND_Stream_GetSyncPoint)(FSOUND_STREAM *stream, int index);
+ char * (F_API *FSOUND_Stream_GetSyncPointInfo)(FSOUND_SYNCPOINT *point, unsigned int *pcmoffset);
+ signed char (F_API *FSOUND_Stream_SetSubStream)(FSOUND_STREAM *stream, int index);
+ int (F_API *FSOUND_Stream_GetNumSubStreams)(FSOUND_STREAM *stream);
+ signed char (F_API *FSOUND_Stream_SetSubStreamSentence)(FSOUND_STREAM *stream, int *sentencelist, int numitems);
+ signed char (F_API *FSOUND_Stream_GetNumTagFields)(FSOUND_STREAM *stream, int *num);
+ signed char (F_API *FSOUND_Stream_GetTagField)(FSOUND_STREAM *stream, int num, int *type, char **name, void **value, int *length);
+ signed char (F_API *FSOUND_Stream_FindTagField)(FSOUND_STREAM *stream, int type, const char *name, void **value, int *length);
+ signed char (F_API *FSOUND_Stream_Net_SetProxy)(const char *proxy);
+ char * (F_API *FSOUND_Stream_Net_GetLastServerStatus)();
+ signed char (F_API *FSOUND_Stream_Net_SetBufferProperties)(int buffersize, int prebuffer_percent, int rebuffer_percent);
+ signed char (F_API *FSOUND_Stream_Net_GetBufferProperties)(int *buffersize, int *prebuffer_percent, int *rebuffer_percent);
+ signed char (F_API *FSOUND_Stream_Net_SetMetadataCallback)(FSOUND_STREAM *stream, FSOUND_METADATACALLBACK callback, void *userdata);
+ signed char (F_API *FSOUND_Stream_Net_GetStatus)(FSOUND_STREAM *stream, int *status, int *bufferpercentused, int *bitrate, unsigned int *flags);
+ signed char (F_API *FSOUND_CD_Play)(char drive, int track);
+ void (F_API *FSOUND_CD_SetPlayMode)(char drive, signed char mode);
+ signed char (F_API *FSOUND_CD_Stop)(char drive);
+ signed char (F_API *FSOUND_CD_SetPaused)(char drive, signed char paused);
+ signed char (F_API *FSOUND_CD_SetVolume)(char drive, int volume);
+ signed char (F_API *FSOUND_CD_SetTrackTime)(char drive, unsigned int ms);
+ signed char (F_API *FSOUND_CD_OpenTray)(char drive, signed char open);
+ signed char (F_API *FSOUND_CD_GetPaused)(char drive);
+ int (F_API *FSOUND_CD_GetTrack)(char drive);
+ int (F_API *FSOUND_CD_GetNumTracks)(char drive);
+ int (F_API *FSOUND_CD_GetVolume)(char drive);
+ int (F_API *FSOUND_CD_GetTrackLength)(char drive, int track);
+ int (F_API *FSOUND_CD_GetTrackTime)(char drive);
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_Create)(FSOUND_DSPCALLBACK callback, int priority, void *userdata);
+ void (F_API *FSOUND_DSP_Free)(FSOUND_DSPUNIT *unit);
+ void (F_API *FSOUND_DSP_SetPriority)(FSOUND_DSPUNIT *unit, int priority);
+ int (F_API *FSOUND_DSP_GetPriority)(FSOUND_DSPUNIT *unit);
+ void (F_API *FSOUND_DSP_SetActive)(FSOUND_DSPUNIT *unit, signed char active);
+ signed char (F_API *FSOUND_DSP_GetActive)(FSOUND_DSPUNIT *unit);
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_GetClearUnit)();
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_GetSFXUnit)();
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_GetMusicUnit)();
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_GetFFTUnit)();
+ FSOUND_DSPUNIT * (F_API *FSOUND_DSP_GetClipAndCopyUnit)();
+ signed char (F_API *FSOUND_DSP_MixBuffers)(void *destbuffer, void *srcbuffer, int len, int freq, int vol, int pan, unsigned int mode);
+ void (F_API *FSOUND_DSP_ClearMixBuffer)();
+ int (F_API *FSOUND_DSP_GetBufferLength)(); /* Length of each DSP update */
+ int (F_API *FSOUND_DSP_GetBufferLengthTotal)(); /* Total buffer length due to FSOUND_SetBufferSize */
+ float * (F_API *FSOUND_DSP_GetSpectrum)(); /* Array of 512 floats - call FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit(), TRUE)) for this to work. */
+ signed char (F_API *FSOUND_Reverb_SetProperties)(FSOUND_REVERB_PROPERTIES *prop);
+ signed char (F_API *FSOUND_Reverb_GetProperties)(FSOUND_REVERB_PROPERTIES *prop);
+ signed char (F_API *FSOUND_Reverb_SetChannelProperties)(int channel, FSOUND_REVERB_CHANNELPROPERTIES *prop);
+ signed char (F_API *FSOUND_Reverb_GetChannelProperties)(int channel, FSOUND_REVERB_CHANNELPROPERTIES *prop);
+ signed char (F_API *FSOUND_Record_SetDriver)(int outputtype);
+ int (F_API *FSOUND_Record_GetNumDrivers)();
+ signed char * (F_API *FSOUND_Record_GetDriverName)(int id);
+ int (F_API *FSOUND_Record_GetDriver)();
+ signed char (F_API *FSOUND_Record_StartSample)(FSOUND_SAMPLE *sptr, signed char loop);
+ signed char (F_API *FSOUND_Record_Stop)();
+ int (F_API *FSOUND_Record_GetPosition)();
+ FMUSIC_MODULE * (F_API *FMUSIC_LoadSong)(const char *name);
+ FMUSIC_MODULE * (F_API *FMUSIC_LoadSongEx)(const char *name_or_data, int offset, int length, unsigned int mode, int *samplelist, int samplelistnum);
+ int (F_API *FMUSIC_GetOpenState)(FMUSIC_MODULE *mod);
+ signed char (F_API *FMUSIC_FreeSong)(FMUSIC_MODULE *mod);
+ signed char (F_API *FMUSIC_PlaySong)(FMUSIC_MODULE *mod);
+ signed char (F_API *FMUSIC_StopSong)(FMUSIC_MODULE *mod);
+ void (F_API *FMUSIC_StopAllSongs)();
+ signed char (F_API *FMUSIC_SetZxxCallback)(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback);
+ signed char (F_API *FMUSIC_SetRowCallback)(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int rowstep);
+ signed char (F_API *FMUSIC_SetOrderCallback)(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int orderstep);
+ signed char (F_API *FMUSIC_SetInstCallback)(FMUSIC_MODULE *mod, FMUSIC_CALLBACK callback, int instrument);
+ signed char (F_API *FMUSIC_SetSample)(FMUSIC_MODULE *mod, int sampno, FSOUND_SAMPLE *sptr);
+ signed char (F_API *FMUSIC_SetUserData)(FMUSIC_MODULE *mod, void *userdata);
+ signed char (F_API *FMUSIC_OptimizeChannels)(FMUSIC_MODULE *mod, int maxchannels, int minvolume);
+ signed char (F_API *FMUSIC_SetReverb)(signed char reverb); /* MIDI only */
+ signed char (F_API *FMUSIC_SetLooping)(FMUSIC_MODULE *mod, signed char looping);
+ signed char (F_API *FMUSIC_SetOrder)(FMUSIC_MODULE *mod, int order);
+ signed char (F_API *FMUSIC_SetPaused)(FMUSIC_MODULE *mod, signed char pause);
+ signed char (F_API *FMUSIC_SetMasterVolume)(FMUSIC_MODULE *mod, int volume);
+ signed char (F_API *FMUSIC_SetMasterSpeed)(FMUSIC_MODULE *mode, float speed);
+ signed char (F_API *FMUSIC_SetPanSeperation)(FMUSIC_MODULE *mod, float pansep);
+ char * (F_API *FMUSIC_GetName)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetType)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetNumOrders)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetNumPatterns)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetNumInstruments)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetNumSamples)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetNumChannels)(FMUSIC_MODULE *mod);
+ FSOUND_SAMPLE * (F_API *FMUSIC_GetSample)(FMUSIC_MODULE *mod, int sampno);
+ int (F_API *FMUSIC_GetPatternLength)(FMUSIC_MODULE *mod, int orderno);
+ signed char (F_API *FMUSIC_IsFinished)(FMUSIC_MODULE *mod);
+ signed char (F_API *FMUSIC_IsPlaying)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetMasterVolume)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetGlobalVolume)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetOrder)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetPattern)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetSpeed)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetBPM)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetRow)(FMUSIC_MODULE *mod);
+ signed char (F_API *FMUSIC_GetPaused)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetTime)(FMUSIC_MODULE *mod);
+ int (F_API *FMUSIC_GetRealChannel)(FMUSIC_MODULE *mod, int modchannel);
+ unsigned int (F_API *FMUSIC_GetUserData)(FMUSIC_MODULE *mod);
+} FMOD_INSTANCE;
+
+
+static FMOD_INSTANCE *FMOD_CreateInstance(char *dllName)
+{
+ FMOD_INSTANCE *instance;
+
+ instance = (FMOD_INSTANCE *)calloc(sizeof(FMOD_INSTANCE), 1);
+ if (!instance)
+ {
+ return NULL;
+ }
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+ instance->module = LoadLibrary(dllName);
+#else
+ instance->module = dlopen(dllName, RTLD_LAZY);
+#endif
+ if (!instance->module)
+ {
+ free(instance);
+ return NULL;
+ }
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+ #define F_GETPROC(_x, _y) \
+ { \
+ *((unsigned int *)&instance->_x) = (unsigned int)GetProcAddress((HMODULE)instance->module, _y); \
+ if (!instance->_x) \
+ { \
+ FreeLibrary((HMODULE)instance->module); \
+ free(instance); \
+ return NULL; \
+ } \
+ }
+#else
+ #define F_GETPROC(_x, _y) \
+ { \
+ char tmp[] = _y; \
+ *(strchr(tmp, '@')) = 0; \
+ *((unsigned int *)&instance->_x) = (unsigned int)dlsym(instance->module, &tmp[1]); \
+ if (!instance->_x) \
+ { \
+ dlclose(instance->module); \
+ free(instance); \
+ return NULL; \
+ } \
+ }
+#endif
+
+ F_GETPROC(FSOUND_SetOutput, "_FSOUND_SetOutput@4");
+ F_GETPROC(FSOUND_SetDriver, "_FSOUND_SetDriver@4");
+ F_GETPROC(FSOUND_SetMixer, "_FSOUND_SetMixer@4");
+ F_GETPROC(FSOUND_SetBufferSize, "_FSOUND_SetBufferSize@4");
+ F_GETPROC(FSOUND_SetHWND, "_FSOUND_SetHWND@4");
+ F_GETPROC(FSOUND_SetMinHardwareChannels, "_FSOUND_SetMinHardwareChannels@4");
+ F_GETPROC(FSOUND_SetMaxHardwareChannels, "_FSOUND_SetMaxHardwareChannels@4");
+ F_GETPROC(FSOUND_SetMemorySystem, "_FSOUND_SetMemorySystem@20");
+ F_GETPROC(FSOUND_Init, "_FSOUND_Init@12");
+ F_GETPROC(FSOUND_Close, "_FSOUND_Close@0");
+ F_GETPROC(FSOUND_Update, "_FSOUND_Update@0");
+ F_GETPROC(FSOUND_SetSFXMasterVolume, "_FSOUND_SetSFXMasterVolume@4");
+ F_GETPROC(FSOUND_SetPanSeperation, "_FSOUND_SetPanSeperation@4");
+ F_GETPROC(FSOUND_SetSpeakerMode, "_FSOUND_SetSpeakerMode@4");
+ F_GETPROC(FSOUND_GetError, "_FSOUND_GetError@0");
+ F_GETPROC(FSOUND_GetVersion, "_FSOUND_GetVersion@0");
+ F_GETPROC(FSOUND_GetOutput, "_FSOUND_GetOutput@0");
+ F_GETPROC(FSOUND_GetOutputHandle, "_FSOUND_GetOutputHandle@0");
+ F_GETPROC(FSOUND_GetDriver, "_FSOUND_GetDriver@0");
+ F_GETPROC(FSOUND_GetMixer, "_FSOUND_GetMixer@0");
+ F_GETPROC(FSOUND_GetNumDrivers, "_FSOUND_GetNumDrivers@0");
+ F_GETPROC(FSOUND_GetDriverName, "_FSOUND_GetDriverName@4");
+ F_GETPROC(FSOUND_GetDriverCaps, "_FSOUND_GetDriverCaps@8");
+ F_GETPROC(FSOUND_GetOutputRate, "_FSOUND_GetOutputRate@0");
+ F_GETPROC(FSOUND_GetMaxChannels, "_FSOUND_GetMaxChannels@0");
+ F_GETPROC(FSOUND_GetMaxSamples, "_FSOUND_GetMaxSamples@0");
+ F_GETPROC(FSOUND_GetSFXMasterVolume, "_FSOUND_GetSFXMasterVolume@0");
+ F_GETPROC(FSOUND_GetNumHWChannels, "_FSOUND_GetNumHWChannels@12");
+ F_GETPROC(FSOUND_GetChannelsPlaying, "_FSOUND_GetChannelsPlaying@0");
+ F_GETPROC(FSOUND_GetCPUUsage, "_FSOUND_GetCPUUsage@0");
+ F_GETPROC(FSOUND_GetMemoryStats, "_FSOUND_GetMemoryStats@8");
+ F_GETPROC(FSOUND_Sample_Load, "_FSOUND_Sample_Load@20");
+ F_GETPROC(FSOUND_Sample_Alloc, "_FSOUND_Sample_Alloc@28");
+ F_GETPROC(FSOUND_Sample_Free, "_FSOUND_Sample_Free@4");
+ F_GETPROC(FSOUND_Sample_Upload, "_FSOUND_Sample_Upload@12");
+ F_GETPROC(FSOUND_Sample_Lock, "_FSOUND_Sample_Lock@28");
+ F_GETPROC(FSOUND_Sample_Unlock, "_FSOUND_Sample_Unlock@20");
+ F_GETPROC(FSOUND_Sample_SetMode, "_FSOUND_Sample_SetMode@8");
+ F_GETPROC(FSOUND_Sample_SetLoopPoints, "_FSOUND_Sample_SetLoopPoints@12");
+ F_GETPROC(FSOUND_Sample_SetDefaults, "_FSOUND_Sample_SetDefaults@20");
+ F_GETPROC(FSOUND_Sample_SetDefaultsEx, "_FSOUND_Sample_SetDefaultsEx@32");
+ F_GETPROC(FSOUND_Sample_SetMinMaxDistance, "_FSOUND_Sample_SetMinMaxDistance@12");
+ F_GETPROC(FSOUND_Sample_SetMaxPlaybacks, "_FSOUND_Sample_SetMaxPlaybacks@8");
+ F_GETPROC(FSOUND_Sample_Get, "_FSOUND_Sample_Get@4");
+ F_GETPROC(FSOUND_Sample_GetName, "_FSOUND_Sample_GetName@4");
+ F_GETPROC(FSOUND_Sample_GetLength, "_FSOUND_Sample_GetLength@4");
+ F_GETPROC(FSOUND_Sample_GetLoopPoints, "_FSOUND_Sample_GetLoopPoints@12");
+ F_GETPROC(FSOUND_Sample_GetDefaults, "_FSOUND_Sample_GetDefaults@20");
+ F_GETPROC(FSOUND_Sample_GetDefaultsEx, "_FSOUND_Sample_GetDefaultsEx@32");
+ F_GETPROC(FSOUND_Sample_GetMode, "_FSOUND_Sample_GetMode@4");
+ F_GETPROC(FSOUND_Sample_GetMinMaxDistance, "_FSOUND_Sample_GetMinMaxDistance@12");
+ F_GETPROC(FSOUND_PlaySound, "_FSOUND_PlaySound@8");
+ F_GETPROC(FSOUND_PlaySoundEx, "_FSOUND_PlaySoundEx@16");
+ F_GETPROC(FSOUND_StopSound, "_FSOUND_StopSound@4");
+ F_GETPROC(FSOUND_SetFrequency, "_FSOUND_SetFrequency@8");
+ F_GETPROC(FSOUND_SetVolume, "_FSOUND_SetVolume@8");
+ F_GETPROC(FSOUND_SetVolumeAbsolute, "_FSOUND_SetVolumeAbsolute@8");
+ F_GETPROC(FSOUND_SetPan, "_FSOUND_SetPan@8");
+ F_GETPROC(FSOUND_SetSurround, "_FSOUND_SetSurround@8");
+ F_GETPROC(FSOUND_SetMute, "_FSOUND_SetMute@8");
+ F_GETPROC(FSOUND_SetPriority, "_FSOUND_SetPriority@8");
+ F_GETPROC(FSOUND_SetReserved, "_FSOUND_SetReserved@8");
+ F_GETPROC(FSOUND_SetPaused, "_FSOUND_SetPaused@8");
+ F_GETPROC(FSOUND_SetLoopMode, "_FSOUND_SetLoopMode@8");
+ F_GETPROC(FSOUND_SetCurrentPosition, "_FSOUND_SetCurrentPosition@8");
+ F_GETPROC(FSOUND_3D_SetAttributes, "_FSOUND_3D_SetAttributes@12");
+ F_GETPROC(FSOUND_3D_SetMinMaxDistance, "_FSOUND_3D_SetMinMaxDistance@12");
+ F_GETPROC(FSOUND_IsPlaying, "_FSOUND_IsPlaying@4");
+ F_GETPROC(FSOUND_GetFrequency, "_FSOUND_GetFrequency@4");
+ F_GETPROC(FSOUND_GetVolume, "_FSOUND_GetVolume@4");
+ F_GETPROC(FSOUND_GetAmplitude, "_FSOUND_GetAmplitude@4");
+ F_GETPROC(FSOUND_GetPan, "_FSOUND_GetPan@4");
+ F_GETPROC(FSOUND_GetSurround, "_FSOUND_GetSurround@4");
+ F_GETPROC(FSOUND_GetMute, "_FSOUND_GetMute@4");
+ F_GETPROC(FSOUND_GetPriority, "_FSOUND_GetPriority@4");
+ F_GETPROC(FSOUND_GetReserved, "_FSOUND_GetReserved@4");
+ F_GETPROC(FSOUND_GetPaused, "_FSOUND_GetPaused@4");
+ F_GETPROC(FSOUND_GetLoopMode, "_FSOUND_GetLoopMode@4");
+ F_GETPROC(FSOUND_GetCurrentPosition, "_FSOUND_GetCurrentPosition@4");
+ F_GETPROC(FSOUND_GetCurrentSample, "_FSOUND_GetCurrentSample@4");
+ F_GETPROC(FSOUND_GetCurrentLevels, "_FSOUND_GetCurrentLevels@12");
+ F_GETPROC(FSOUND_GetNumSubChannels, "_FSOUND_GetNumSubChannels@4");
+ F_GETPROC(FSOUND_GetSubChannel, "_FSOUND_GetSubChannel@8");
+ F_GETPROC(FSOUND_3D_GetAttributes, "_FSOUND_3D_GetAttributes@12");
+ F_GETPROC(FSOUND_3D_GetMinMaxDistance, "_FSOUND_3D_GetMinMaxDistance@12");
+ F_GETPROC(FSOUND_3D_Listener_SetCurrent, "_FSOUND_3D_Listener_SetCurrent@8");
+ F_GETPROC(FSOUND_3D_Listener_SetAttributes, "_FSOUND_3D_Listener_SetAttributes@32");
+ F_GETPROC(FSOUND_3D_Listener_GetAttributes, "_FSOUND_3D_Listener_GetAttributes@32");
+ F_GETPROC(FSOUND_3D_SetDopplerFactor, "_FSOUND_3D_SetDopplerFactor@4");
+ F_GETPROC(FSOUND_3D_SetDistanceFactor, "_FSOUND_3D_SetDistanceFactor@4");
+ F_GETPROC(FSOUND_3D_SetRolloffFactor, "_FSOUND_3D_SetRolloffFactor@4");
+ F_GETPROC(FSOUND_FX_Enable, "_FSOUND_FX_Enable@8");
+ F_GETPROC(FSOUND_FX_Disable, "_FSOUND_FX_Disable@4");
+ F_GETPROC(FSOUND_FX_SetChorus, "_FSOUND_FX_SetChorus@32");
+ F_GETPROC(FSOUND_FX_SetCompressor, "_FSOUND_FX_SetCompressor@28");
+ F_GETPROC(FSOUND_FX_SetDistortion, "_FSOUND_FX_SetDistortion@24");
+ F_GETPROC(FSOUND_FX_SetEcho, "_FSOUND_FX_SetEcho@24");
+ F_GETPROC(FSOUND_FX_SetFlanger, "_FSOUND_FX_SetFlanger@32");
+ F_GETPROC(FSOUND_FX_SetGargle, "_FSOUND_FX_SetGargle@12");
+ F_GETPROC(FSOUND_FX_SetI3DL2Reverb, "_FSOUND_FX_SetI3DL2Reverb@52");
+ F_GETPROC(FSOUND_FX_SetParamEQ, "_FSOUND_FX_SetParamEQ@16");
+ F_GETPROC(FSOUND_FX_SetWavesReverb, "_FSOUND_FX_SetWavesReverb@20");
+ F_GETPROC(FSOUND_Stream_Open, "_FSOUND_Stream_Open@16");
+ F_GETPROC(FSOUND_Stream_Create, "_FSOUND_Stream_Create@20");
+ F_GETPROC(FSOUND_Stream_Play, "_FSOUND_Stream_Play@8");
+ F_GETPROC(FSOUND_Stream_PlayEx, "_FSOUND_Stream_PlayEx@16");
+ F_GETPROC(FSOUND_Stream_Stop, "_FSOUND_Stream_Stop@4");
+ F_GETPROC(FSOUND_Stream_Close, "_FSOUND_Stream_Close@4");
+ F_GETPROC(FSOUND_Stream_SetEndCallback, "_FSOUND_Stream_SetEndCallback@12");
+ F_GETPROC(FSOUND_Stream_SetSyncCallback, "_FSOUND_Stream_SetSyncCallback@12");
+ F_GETPROC(FSOUND_Stream_GetSample, "_FSOUND_Stream_GetSample@4");
+ F_GETPROC(FSOUND_Stream_CreateDSP, "_FSOUND_Stream_CreateDSP@16");
+ F_GETPROC(FSOUND_Stream_SetBufferSize, "_FSOUND_Stream_SetBufferSize@4");
+ F_GETPROC(FSOUND_Stream_SetPosition, "_FSOUND_Stream_SetPosition@8");
+ F_GETPROC(FSOUND_Stream_GetPosition, "_FSOUND_Stream_GetPosition@4");
+ F_GETPROC(FSOUND_Stream_SetTime, "_FSOUND_Stream_SetTime@8");
+ F_GETPROC(FSOUND_Stream_GetTime, "_FSOUND_Stream_GetTime@4");
+ F_GETPROC(FSOUND_Stream_GetLength, "_FSOUND_Stream_GetLength@4");
+ F_GETPROC(FSOUND_Stream_GetLengthMs, "_FSOUND_Stream_GetLengthMs@4");
+ F_GETPROC(FSOUND_Stream_SetMode, "_FSOUND_Stream_SetMode@8");
+ F_GETPROC(FSOUND_Stream_GetMode, "_FSOUND_Stream_GetMode@4");
+ F_GETPROC(FSOUND_Stream_SetSubStream, "_FSOUND_Stream_SetSubStream@8");
+ F_GETPROC(FSOUND_Stream_GetNumSubStreams, "_FSOUND_Stream_GetNumSubStreams@4");
+ F_GETPROC(FSOUND_Stream_SetSubStreamSentence, "_FSOUND_Stream_SetSubStreamSentence@12");
+ F_GETPROC(FSOUND_Stream_SetLoopPoints, "_FSOUND_Stream_SetLoopPoints@12");
+ F_GETPROC(FSOUND_Stream_SetLoopCount, "_FSOUND_Stream_SetLoopCount@8");
+ F_GETPROC(FSOUND_Stream_AddSyncPoint, "_FSOUND_Stream_AddSyncPoint@12");
+ F_GETPROC(FSOUND_Stream_DeleteSyncPoint, "_FSOUND_Stream_DeleteSyncPoint@4");
+ F_GETPROC(FSOUND_Stream_GetNumSyncPoints, "_FSOUND_Stream_GetNumSyncPoints@4");
+ F_GETPROC(FSOUND_Stream_GetSyncPoint, "_FSOUND_Stream_GetSyncPoint@8");
+ F_GETPROC(FSOUND_Stream_GetSyncPointInfo, "_FSOUND_Stream_GetSyncPointInfo@8");
+ F_GETPROC(FSOUND_Stream_GetOpenState, "_FSOUND_Stream_GetOpenState@4");
+ F_GETPROC(FSOUND_Stream_GetNumTagFields, "_FSOUND_Stream_GetNumTagFields@8");
+ F_GETPROC(FSOUND_Stream_GetTagField, "_FSOUND_Stream_GetTagField@24");
+ F_GETPROC(FSOUND_Stream_FindTagField, "_FSOUND_Stream_FindTagField@20");
+ F_GETPROC(FSOUND_Stream_Net_SetProxy, "_FSOUND_Stream_Net_SetProxy@4");
+ F_GETPROC(FSOUND_Stream_Net_GetLastServerStatus, "_FSOUND_Stream_Net_GetLastServerStatus@0");
+ F_GETPROC(FSOUND_Stream_Net_SetBufferProperties, "_FSOUND_Stream_Net_SetBufferProperties@12");
+ F_GETPROC(FSOUND_Stream_Net_GetBufferProperties, "_FSOUND_Stream_Net_GetBufferProperties@12");
+ F_GETPROC(FSOUND_Stream_Net_SetMetadataCallback, "_FSOUND_Stream_Net_SetMetadataCallback@12");
+ F_GETPROC(FSOUND_Stream_Net_GetStatus, "_FSOUND_Stream_Net_GetStatus@20");
+ F_GETPROC(FSOUND_CD_Play, "_FSOUND_CD_Play@8");
+ F_GETPROC(FSOUND_CD_SetPlayMode, "_FSOUND_CD_SetPlayMode@8");
+ F_GETPROC(FSOUND_CD_Stop, "_FSOUND_CD_Stop@4");
+ F_GETPROC(FSOUND_CD_SetPaused, "_FSOUND_CD_SetPaused@8");
+ F_GETPROC(FSOUND_CD_SetVolume, "_FSOUND_CD_SetVolume@8");
+ F_GETPROC(FSOUND_CD_SetTrackTime, "_FSOUND_CD_SetTrackTime@8");
+ F_GETPROC(FSOUND_CD_OpenTray, "_FSOUND_CD_OpenTray@8");
+ F_GETPROC(FSOUND_CD_GetPaused, "_FSOUND_CD_GetPaused@4");
+ F_GETPROC(FSOUND_CD_GetTrack, "_FSOUND_CD_GetTrack@4");
+ F_GETPROC(FSOUND_CD_GetNumTracks, "_FSOUND_CD_GetNumTracks@4");
+ F_GETPROC(FSOUND_CD_GetVolume, "_FSOUND_CD_GetVolume@4");
+ F_GETPROC(FSOUND_CD_GetTrackLength, "_FSOUND_CD_GetTrackLength@8");
+ F_GETPROC(FSOUND_CD_GetTrackTime, "_FSOUND_CD_GetTrackTime@4");
+ F_GETPROC(FSOUND_DSP_Create, "_FSOUND_DSP_Create@12");
+ F_GETPROC(FSOUND_DSP_Free, "_FSOUND_DSP_Free@4");
+ F_GETPROC(FSOUND_DSP_SetPriority, "_FSOUND_DSP_SetPriority@8");
+ F_GETPROC(FSOUND_DSP_GetPriority, "_FSOUND_DSP_GetPriority@4");
+ F_GETPROC(FSOUND_DSP_SetActive, "_FSOUND_DSP_SetActive@8");
+ F_GETPROC(FSOUND_DSP_GetActive, "_FSOUND_DSP_GetActive@4");
+ F_GETPROC(FSOUND_DSP_GetClearUnit, "_FSOUND_DSP_GetClearUnit@0");
+ F_GETPROC(FSOUND_DSP_GetSFXUnit, "_FSOUND_DSP_GetSFXUnit@0");
+ F_GETPROC(FSOUND_DSP_GetMusicUnit, "_FSOUND_DSP_GetMusicUnit@0");
+ F_GETPROC(FSOUND_DSP_GetClipAndCopyUnit, "_FSOUND_DSP_GetClipAndCopyUnit@0");
+ F_GETPROC(FSOUND_DSP_GetFFTUnit, "_FSOUND_DSP_GetFFTUnit@0");
+ F_GETPROC(FSOUND_DSP_MixBuffers, "_FSOUND_DSP_MixBuffers@28");
+ F_GETPROC(FSOUND_DSP_ClearMixBuffer, "_FSOUND_DSP_ClearMixBuffer@0");
+ F_GETPROC(FSOUND_DSP_GetBufferLength, "_FSOUND_DSP_GetBufferLength@0");
+ F_GETPROC(FSOUND_DSP_GetBufferLengthTotal, "_FSOUND_DSP_GetBufferLengthTotal@0");
+ F_GETPROC(FSOUND_DSP_GetSpectrum, "_FSOUND_DSP_GetSpectrum@0");
+ F_GETPROC(FSOUND_Reverb_SetProperties, "_FSOUND_Reverb_SetProperties@4");
+ F_GETPROC(FSOUND_Reverb_GetProperties, "_FSOUND_Reverb_GetProperties@4");
+ F_GETPROC(FSOUND_Reverb_SetChannelProperties, "_FSOUND_Reverb_SetChannelProperties@8");
+ F_GETPROC(FSOUND_Reverb_GetChannelProperties, "_FSOUND_Reverb_GetChannelProperties@8");
+ F_GETPROC(FSOUND_Record_SetDriver, "_FSOUND_Record_SetDriver@4");
+ F_GETPROC(FSOUND_Record_GetNumDrivers, "_FSOUND_Record_GetNumDrivers@0");
+ F_GETPROC(FSOUND_Record_GetDriverName, "_FSOUND_Record_GetDriverName@4");
+ F_GETPROC(FSOUND_Record_GetDriver, "_FSOUND_Record_GetDriver@0");
+ F_GETPROC(FSOUND_Record_StartSample, "_FSOUND_Record_StartSample@8");
+ F_GETPROC(FSOUND_Record_Stop, "_FSOUND_Record_Stop@0");
+ F_GETPROC(FSOUND_Record_GetPosition, "_FSOUND_Record_GetPosition@0");
+ F_GETPROC(FSOUND_File_SetCallbacks, "_FSOUND_File_SetCallbacks@20");
+ F_GETPROC(FMUSIC_LoadSong, "_FMUSIC_LoadSong@4");
+ F_GETPROC(FMUSIC_LoadSongEx, "_FMUSIC_LoadSongEx@24");
+ F_GETPROC(FMUSIC_GetOpenState, "_FMUSIC_GetOpenState@4");
+ F_GETPROC(FMUSIC_FreeSong, "_FMUSIC_FreeSong@4");
+ F_GETPROC(FMUSIC_PlaySong, "_FMUSIC_PlaySong@4");
+ F_GETPROC(FMUSIC_StopSong, "_FMUSIC_StopSong@4");
+ F_GETPROC(FMUSIC_StopAllSongs, "_FMUSIC_StopAllSongs@0");
+ F_GETPROC(FMUSIC_SetZxxCallback, "_FMUSIC_SetZxxCallback@8");
+ F_GETPROC(FMUSIC_SetRowCallback, "_FMUSIC_SetRowCallback@12");
+ F_GETPROC(FMUSIC_SetOrderCallback, "_FMUSIC_SetOrderCallback@12");
+ F_GETPROC(FMUSIC_SetInstCallback, "_FMUSIC_SetInstCallback@12");
+ F_GETPROC(FMUSIC_SetSample, "_FMUSIC_SetSample@12");
+ F_GETPROC(FMUSIC_SetUserData, "_FMUSIC_SetUserData@8");
+ F_GETPROC(FMUSIC_OptimizeChannels, "_FMUSIC_OptimizeChannels@12");
+ F_GETPROC(FMUSIC_SetReverb, "_FMUSIC_SetReverb@4");
+ F_GETPROC(FMUSIC_SetLooping, "_FMUSIC_SetLooping@8");
+ F_GETPROC(FMUSIC_SetOrder, "_FMUSIC_SetOrder@8");
+ F_GETPROC(FMUSIC_SetPaused, "_FMUSIC_SetPaused@8");
+ F_GETPROC(FMUSIC_SetMasterVolume, "_FMUSIC_SetMasterVolume@8");
+ F_GETPROC(FMUSIC_SetMasterSpeed, "_FMUSIC_SetMasterSpeed@8");
+ F_GETPROC(FMUSIC_SetPanSeperation, "_FMUSIC_SetPanSeperation@8");
+ F_GETPROC(FMUSIC_GetName, "_FMUSIC_GetName@4");
+ F_GETPROC(FMUSIC_GetType, "_FMUSIC_GetType@4");
+ F_GETPROC(FMUSIC_GetNumOrders, "_FMUSIC_GetNumOrders@4");
+ F_GETPROC(FMUSIC_GetNumPatterns, "_FMUSIC_GetNumPatterns@4");
+ F_GETPROC(FMUSIC_GetNumInstruments, "_FMUSIC_GetNumInstruments@4");
+ F_GETPROC(FMUSIC_GetNumSamples, "_FMUSIC_GetNumSamples@4");
+ F_GETPROC(FMUSIC_GetNumChannels, "_FMUSIC_GetNumChannels@4");
+ F_GETPROC(FMUSIC_GetSample, "_FMUSIC_GetSample@8");
+ F_GETPROC(FMUSIC_GetPatternLength, "_FMUSIC_GetPatternLength@8");
+ F_GETPROC(FMUSIC_IsFinished, "_FMUSIC_IsFinished@4");
+ F_GETPROC(FMUSIC_IsPlaying, "_FMUSIC_IsPlaying@4");
+ F_GETPROC(FMUSIC_GetMasterVolume, "_FMUSIC_GetMasterVolume@4");
+ F_GETPROC(FMUSIC_GetGlobalVolume, "_FMUSIC_GetGlobalVolume@4");
+ F_GETPROC(FMUSIC_GetOrder, "_FMUSIC_GetOrder@4");
+ F_GETPROC(FMUSIC_GetPattern, "_FMUSIC_GetPattern@4");
+ F_GETPROC(FMUSIC_GetSpeed, "_FMUSIC_GetSpeed@4");
+ F_GETPROC(FMUSIC_GetBPM, "_FMUSIC_GetBPM@4");
+ F_GETPROC(FMUSIC_GetRow, "_FMUSIC_GetRow@4");
+ F_GETPROC(FMUSIC_GetPaused, "_FMUSIC_GetPaused@4");
+ F_GETPROC(FMUSIC_GetTime, "_FMUSIC_GetTime@4");
+ F_GETPROC(FMUSIC_GetRealChannel, "_FMUSIC_GetRealChannel@8");
+ F_GETPROC(FMUSIC_GetUserData, "_FMUSIC_GetUserData@4");
+
+ return instance;
+}
+
+static void FMOD_FreeInstance(FMOD_INSTANCE *instance)
+{
+ if (instance)
+ {
+ if (instance->module)
+ {
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+ FreeLibrary((HMODULE)instance->module);
+#else
+ dlclose(instance->module);
+#endif
+ }
+ free(instance);
+ }
+}
+
+#endif
+
--- /dev/null
+#ifndef _LUGARU_GL_H_
+#define _LUGARU_GL_H_
+
+
+#include <cstring>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <map>
+#include <string>
+
+#ifndef WIN32
+
+#include <gl.h>
+#include <glu.h>
+#include <glext.h>
+
+#else
+
+#define WIN32_LEAN_AND_MEAN
+#define Polygon WinPolygon
+#include <windows.h>
+#undef Polygon
+#define GL_GLEXT_PROTOTYPES
+#include <gl/gl.h>
+#include <gl/glu.h>
+#include <gl/glaux.h>
+#include <gl/glext.h>
+#include "WinDefs.h"
+#include "il/ilut.h"
+
+#define glDeleteTextures( a, b) glDeleteTextures( (a), (const unsigned int *)(b) );
+
+struct RGBColor
+{
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+};
+typedef struct RGBColor RGBColor;
+typedef RGBColor * RGBColorPtr;
+
+#endif
+
+using namespace std;
+
+#include "logger/logger.h"
+
+#endif
\ No newline at end of file
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _
+// | |
+// | | ___ __ _ __ _ ___ _ __ ___ _ __ _ __
+// | |/ _ \ / _` |/ _` |/ _ \ '__| / __| '_ \| '_ \
+// | | (_) | (_| | (_| | __/ | _ | (__| |_) | |_) |
+// |_|\___/ \__, |\__, |\___|_| (_) \___| .__/| .__/
+// __/ | __/ | | | | |
+// |___/ |___/ |_| |_|
+//
+// Generic informational logging class
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 07/06/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#include "stdafx.h" // If this line gives you an error, comment it out
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+//#include <strstream>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctime>
+using namespace std;
+
+#include "logger.h"
+
+class LogFunc
+{
+public:
+ LogFunc(void) {}
+
+ void pushMessage(const std::string & str)
+ {
+ entries.push_back(str);
+ }
+
+ void dump(std::ostream & os)
+ {
+ std::list<std::string>::iterator it = entries.begin();
+ for (; it != entries.end(); ++it)
+ {
+ os << *it;
+ }
+ }
+
+private:
+ std::list<std::string> entries;
+};
+
+class LogStack
+{
+public:
+ LogStack(void)
+ {
+ pushFunc();
+ }
+
+ void pushFunc(void)
+ {
+ entries.push_back(LogFunc());
+ }
+
+ void popFunc(void)
+ {
+ if (entries.size() > 1)
+ {
+ entries.pop_back();
+ }
+ }
+
+ void logMessage(const std::string & str_)
+ {
+ entries.back().pushMessage(str_);
+ }
+
+ void dump(std::ostream & os)
+ {
+ std::list<LogFunc>::iterator it = entries.begin();
+ for (; it != entries.end(); ++it)
+ {
+ it->dump(os);
+ }
+ }
+
+private:
+ std::list<LogFunc> entries;
+};
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The global log stack object
+// ---------------------------------------------------------------------------------------------------------------------------------
+LogStack logStack;
+
+void pushFunc(void) {logStack.pushFunc();}
+void popFunc(void) {logStack.popFunc();}
+
+void dumpLog(void)
+{
+ ofstream of(logger.logFile().c_str(), ios::out | ios::trunc);
+ if (!of) return;
+ logStack.dump(of);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The global logger object
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+Logger logger;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+#ifdef _DEBUG
+void Logger::limitFileSize() const
+{
+ if (fileSizeLimit() < 0) return;
+ struct _stat sbuf;
+ _stat(logFile().c_str(), &sbuf);
+ if (sbuf.st_size > fileSizeLimit())
+ {
+ unlink(logFile().c_str());
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::start(const bool reset)
+{
+ std::stringstream ss;
+
+ if (logStarted()) return;
+ _logStarted = true;
+
+ // Get the time
+
+ time_t t = time(NULL);
+ string ts = asctime(localtime(&t));
+ ts[ts.length() - 1] = 0;
+
+ // Start the log
+
+ //limitFileSize();
+ //ofstream of(logFile().c_str(), ios::out | (reset ? ios::trunc : ios::app));
+ //if (!of) return;
+
+ //of << "---------------------------------------------- Log begins on " << ts << " ----------------------------------------------" << endl;
+ ss << "---------------------------------------------- Log begins on " << ts << " ----------------------------------------------" << endl;
+ logStack.logMessage(ss.str());
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::stop()
+{
+ std::stringstream ss;
+
+ // Automatic One time only startup
+
+ if (!logStarted()) return;
+ _logStarted = false;
+
+ // Get the time
+
+ time_t t = time(NULL);
+ string ts = asctime(localtime(&t));
+ ts.erase(ts.length() - 1);
+
+ // Stop the log
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ //of << "----------------------------------------------- Log ends on " << ts << " -----------------------------------------------" << endl << endl;
+ ss << "----------------------------------------------- Log ends on " << ts << " -----------------------------------------------" << endl << endl;
+ logStack.logMessage(ss.str());
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logTex(const string &s, const LogFlags logBits)
+{
+ std::stringstream ss;
+
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Output to the log file
+
+ //of << headerString(logBits) << s << endl;
+ ss << headerString(logBits) << s << endl;
+ logStack.logMessage(ss.str());
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logRaw(const string &s)
+{
+ std::stringstream ss;
+
+ // Open the file
+
+ //limitFileSize();
+ //ofstream of(logFile().c_str(), ios::out|ios::app);
+ //if (!of) return;
+
+ // Log the output
+
+ //of << s << endl;
+ ss << s << endl;
+ logStack.logMessage(ss.str());
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logHex(const char *buffer, const unsigned int count, const LogFlags logBits)
+{
+ std::stringstream ss;
+
+ // No input? No output
+
+ if (!buffer) return;
+
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ //limitFileSize();
+ //ofstream of(logFile().c_str(), ios::out|ios::app);
+ //if (!of) return;
+
+ // Log the output
+
+ unsigned int logged = 0;
+ while(logged < count)
+ {
+ // One line at a time...
+
+ string line;
+
+ // The number of characters per line
+
+ unsigned int hexLength = 20;
+
+ // Default the buffer
+
+ unsigned int i;
+ for (i = 0; i < hexLength; i++)
+ {
+ line += "-- ";
+ }
+
+ for (i = 0; i < hexLength; i++)
+ {
+ line += ".";
+ }
+
+ // Fill it in with real data
+
+ for (i = 0; i < hexLength && logged < count; i++, logged++)
+ {
+ unsigned char byte = buffer[logged];
+ unsigned int index = i * 3;
+
+ // The hex characters
+
+ const string hexlist("0123456789ABCDEF");
+ line[index+0] = hexlist[byte >> 4];
+ line[index+1] = hexlist[byte & 0xf];
+
+ // The ascii characters
+
+ if (byte < 0x20 || byte > 0x7f) byte = '.';
+ line[(hexLength*3)+i+0] = byte;
+ }
+
+ // Write it to the log file
+
+ //of << headerString(logBits) << line << endl;
+ ss << headerString(logBits) << line << endl;
+ logStack.logMessage(ss.str());
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::indent(const string &s, const LogFlags logBits)
+{
+ std::stringstream ss;
+
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ //limitFileSize();
+ //ofstream of(logFile().c_str(), ios::out|ios::app);
+ //if (!of) return;
+
+ // Log the output
+
+ //if (lineCharsFlag()) of << headerString(logBits) << "\xDA\xC4\xC4" << s << endl;
+ //else of << headerString(logBits) << "+- " << s << endl;
+
+ if (lineCharsFlag()) ss << headerString(logBits) << "\xDA\xC4\xC4" << s << endl;
+ else ss << headerString(logBits) << "+- " << s << endl;
+ logStack.logMessage(ss.str());
+
+ // Indent...
+
+ _indentCount += _indentChars;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::undent(const string &s, const LogFlags logBits)
+{
+ std::stringstream ss;
+
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Undo the indentation
+
+ _indentCount -= _indentChars;
+ if (_indentCount < 0) _indentCount = 0;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Log the output
+
+ //if (lineCharsFlag()) of << headerString(logBits) << "\xC0\xC4\xC4" << s << endl;
+ //else of << headerString(logBits) << "+- " << s << endl;
+
+ if (lineCharsFlag()) ss << headerString(logBits) << "\xC0\xC4\xC4" << s << endl;
+ else ss << headerString(logBits) << "+- " << s << endl;
+ logStack.logMessage(ss.str());
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+const string &Logger::headerString(const LogFlags logBits) const
+{
+ static string headerString;
+ headerString.erase();
+
+ // Get the string that represents the bits
+
+ switch(logBits)
+ {
+ case LOG_INDENT : headerString += "> "; break;
+ case LOG_UNDENT : headerString += "< "; break;
+ case LOG_ALL : headerString += "A "; break;
+ case LOG_CRIT : headerString += "! "; break;
+ case LOG_DATA : headerString += "D "; break;
+ case LOG_ERR : headerString += "E "; break;
+ case LOG_FLOW : headerString += "F "; break;
+ case LOG_INFO : headerString += "I "; break;
+ case LOG_WARN : headerString += "W "; break;
+ default: headerString += " "; break;
+ }
+
+ // File string (strip out the path)
+
+ char temp[1024];
+ int ix = sourceFile().rfind('\\');
+ ix = (ix == (int) string::npos ? 0: ix+1);
+ sprintf(temp, "%25s[%04d]", sourceFile().substr(ix).c_str(), sourceLine());
+ headerString += temp;
+
+ // Time string (specially formatted to save room)
+
+ time_t t = time(NULL);
+ struct tm *tme = localtime(&t);
+ sprintf(temp, "%02d/%02d %02d:%02d ", tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min);
+ headerString += temp;
+
+ // Spaces for indentation
+
+ memset(temp, ' ', sizeof(temp));
+ temp[_indentCount] = '\0';
+
+ // Add the indentation markers
+
+ int count = 0;
+ while(count < _indentCount)
+ {
+ if (lineCharsFlag()) temp[count] = '\xB3';
+ else temp[count] = '|';
+ count += _indentChars;
+ }
+ headerString += temp;
+
+ return headerString;
+}
+
+#else /*Release Build*/
+ std::string release_Null;
+ void Logger::limitFileSize() const {}
+ const string &Logger::headerString(const LogFlags logBits) const{return release_Null;}
+ void Logger::start(const bool reset){}
+ void Logger::stop(){}
+ void Logger::logTex(const string &s, const LogFlags logBits /*= LOG_INFO*/){}
+ void Logger::logRaw(const string &s){}
+ void Logger::logHex(const char *buffer, const unsigned int count, const LogFlags logBits /*= LOG_INFO*/){}
+ void Logger::indent(const string &s, const LogFlags logBits /*= LOG_INDENT*/){}
+ void Logger::undent(const string &s, const LogFlags logBits /*= LOG_UNDENT*/){}
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// logger.cpp - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _ _
+// | | | |
+// | | ___ __ _ __ _ ___ _ __ | |__
+// | |/ _ \ / _` |/ _` |/ _ \ '__| | '_ \
+// | | (_) | (_| | (_| | __/ | _ | | | |
+// |_|\___/ \__, |\__, |\___|_| (_)|_| |_|
+// __/ | __/ |
+// |___/ |___/
+//
+// Generic informational logging class
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 07/06/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifndef _H_LOGGER
+#define _H_LOGGER
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The global logger
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class Logger;
+extern Logger logger;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Macros (necessary evil to take advantage of __LINE__ and __FILE__)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#define LOG logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logTex
+#define HEX logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logHex
+#define RAW logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logRaw
+#define INDENT logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.indent
+#define UNDENT logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.undent
+#define LOGBLOCK logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogBlock __lb__
+
+// If you compiler supports __FUNCTION__, then replace the "#if 1" with "#if 0". Note that this will change the usage of the macro
+
+#if 0
+#define LOGFUNC logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogFlow __lf__
+#else
+#define LOGFUNC logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogFlow __lf__(__FUNCTION__)
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The logger class: does the actual logging
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class Logger
+{
+public:
+ // Enumerations
+
+ enum LogFlags
+ {
+ LOG_INDENT = 0x00000001,
+ LOG_UNDENT = 0x00000002,
+ LOG_FLOW = 0x00000004,
+ LOG_BLOK = 0x00000008,
+ LOG_DATA = 0x00000010,
+ LOG_INFO = 0x00000012,
+ LOG_WARN = 0x00000014,
+ LOG_ERR = 0x00000018,
+ LOG_CRIT = 0x00000020,
+ LOG_ALL = 0xFFFFFFFF
+ };
+
+ // Construction/Destruction
+
+inline Logger()
+ : _sourceLine(0), _indentCount(0), _indentChars(4), _fileSizeLimit(-1), _logMask(LOG_ALL),
+ _logStarted(false), _lineCharsFlag(false), _logFile("logger.log")
+ {
+ }
+
+virtual ~Logger()
+ {
+ stop();
+ }
+
+ // Operators
+
+inline void operator +=(const string &s) {logTex(s);}
+
+ // Accessors
+
+inline const bool &lineCharsFlag() const {return _lineCharsFlag;}
+inline bool &lineCharsFlag() {return _lineCharsFlag;}
+
+inline const int &fileSizeLimit() const {return _fileSizeLimit;}
+inline int &fileSizeLimit() {return _fileSizeLimit;}
+
+inline const unsigned int &logMask() const {return _logMask;}
+inline unsigned int &logMask() {return _logMask;}
+
+inline const string &logFile() const {return _logFile;}
+inline string &logFile() {return _logFile;}
+
+inline const unsigned int &sourceLine() const {return _sourceLine;}
+inline unsigned int &sourceLine() {return _sourceLine;}
+
+inline const string &sourceFile() const {return _sourceFile;}
+inline string &sourceFile() {return _sourceFile;}
+
+inline bool logStarted() const {return _logStarted;}
+
+ // Utilitarian (public)
+
+virtual void start(const bool reset);
+virtual void stop();
+virtual void logTex(const string &s, const LogFlags logBits = LOG_INFO);
+virtual void logRaw(const string &s);
+virtual void logHex(const char *buffer, const unsigned int count, const LogFlags logBits = LOG_INFO);
+virtual void indent(const string &s, const LogFlags logBits = LOG_INDENT);
+virtual void undent(const string &s, const LogFlags logBits = LOG_UNDENT);
+
+private:
+ // Utilitarian (private)
+
+virtual void limitFileSize() const;
+virtual const string &headerString(const LogFlags logBits) const;
+
+ // Data
+
+ string _logFile;
+ string _sourceFile;
+ unsigned int _sourceLine;
+ int _indentCount;
+ int _indentChars;
+ int _fileSizeLimit;
+ unsigned int _logMask;
+ bool _logStarted;
+ bool _lineCharsFlag;
+};
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The LogBlock class: used for automatic indentation
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class LogBlock
+{
+public:
+inline LogBlock(const string &s) {str = s;logger.indent("Begin block: " + str, Logger::LOG_INDENT);}
+inline ~LogBlock() {logger.undent("", Logger::LOG_UNDENT);}
+private:
+ string str;
+};
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The LogFlow class: used for logging code flow
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void pushFunc(void);
+void popFunc(void);
+void dumpLog(void);
+
+class LogFlow
+{
+public:
+inline LogFlow(const string &function) {pushFunc(); str = function;logger.indent(str, Logger::LOG_FLOW);}
+inline ~LogFlow() {logger.undent("", Logger::LOG_FLOW); popFunc();}
+private:
+ string str;
+};
+
+#endif // _H_LOGGER
+// ---------------------------------------------------------------------------------------------------------------------------------
+// logger.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _
+// | |
+// | | ___ __ _ __ _ ___ _ __ ___ _ __ _ __
+// | |/ _ \ / _` |/ _` |/ _ \ '__| / __| '_ \| '_ \
+// | | (_) | (_| | (_| | __/ | _ | (__| |_) | |_) |
+// |_|\___/ \__, |\__, |\___|_| (_) \___| .__/| .__/
+// __/ | __/ | | | | |
+// |___/ |___/ |_| |_|
+//
+// Generic informational logging class
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 07/06/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#include "stdafx.h" // If this line gives you an error, comment it out
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <strstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctime>
+using namespace std;
+
+#include "logger.h"
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The global logger object
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+Logger logger;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+#ifdef _DEBUG
+void Logger::limitFileSize() const
+{
+ if (fileSizeLimit() < 0) return;
+ struct _stat sbuf;
+ _stat(logFile().c_str(), &sbuf);
+ if (sbuf.st_size > fileSizeLimit())
+ {
+ unlink(logFile().c_str());
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::start(const bool reset)
+{
+ if (logStarted()) return;
+ _logStarted = true;
+
+ // Get the time
+
+ time_t t = time(NULL);
+ string ts = asctime(localtime(&t));
+ ts[ts.length() - 1] = 0;
+
+ // Start the log
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out | (reset ? ios::trunc : ios::app));
+ if (!of) return;
+
+ of << "---------------------------------------------- Log begins on " << ts << " ----------------------------------------------" << endl;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::stop()
+{
+ // Automatic One time only startup
+
+ if (!logStarted()) return;
+ _logStarted = false;
+
+ // Get the time
+
+ time_t t = time(NULL);
+ string ts = asctime(localtime(&t));
+ ts.erase(ts.length() - 1);
+
+ // Stop the log
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ of << "----------------------------------------------- Log ends on " << ts << " -----------------------------------------------" << endl << endl;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logTex(const string &s, const LogFlags logBits)
+{
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Output to the log file
+
+ of << headerString(logBits) << s << endl;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logRaw(const string &s)
+{
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Log the output
+
+ of << s << endl;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::logHex(const char *buffer, const unsigned int count, const LogFlags logBits)
+{
+ // No input? No output
+
+ if (!buffer) return;
+
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Log the output
+
+ unsigned int logged = 0;
+ while(logged < count)
+ {
+ // One line at a time...
+
+ string line;
+
+ // The number of characters per line
+
+ unsigned int hexLength = 20;
+
+ // Default the buffer
+
+ unsigned int i;
+ for (i = 0; i < hexLength; i++)
+ {
+ line += "-- ";
+ }
+
+ for (i = 0; i < hexLength; i++)
+ {
+ line += ".";
+ }
+
+ // Fill it in with real data
+
+ for (i = 0; i < hexLength && logged < count; i++, logged++)
+ {
+ unsigned char byte = buffer[logged];
+ unsigned int index = i * 3;
+
+ // The hex characters
+
+ const string hexlist("0123456789ABCDEF");
+ line[index+0] = hexlist[byte >> 4];
+ line[index+1] = hexlist[byte & 0xf];
+
+ // The ascii characters
+
+ if (byte < 0x20 || byte > 0x7f) byte = '.';
+ line[(hexLength*3)+i+0] = byte;
+ }
+
+ // Write it to the log file
+
+ of << headerString(logBits) << line << endl;
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::indent(const string &s, const LogFlags logBits)
+{
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Log the output
+
+ if (lineCharsFlag()) of << headerString(logBits) << "\xDA\xC4\xC4" << s << endl;
+ else of << headerString(logBits) << "+- " << s << endl;
+
+ // Indent...
+
+ _indentCount += _indentChars;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void Logger::undent(const string &s, const LogFlags logBits)
+{
+ // If the bits don't match the mask, then bail
+
+ if (!(logBits & logMask())) return;
+
+ // Undo the indentation
+
+ _indentCount -= _indentChars;
+ if (_indentCount < 0) _indentCount = 0;
+
+ // Open the file
+
+ limitFileSize();
+ ofstream of(logFile().c_str(), ios::out|ios::app);
+ if (!of) return;
+
+ // Log the output
+
+ if (lineCharsFlag()) of << headerString(logBits) << "\xC0\xC4\xC4" << s << endl;
+ else of << headerString(logBits) << "+- " << s << endl;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+const string &Logger::headerString(const LogFlags logBits) const
+{
+ static string headerString;
+ headerString.erase();
+
+ // Get the string that represents the bits
+
+ switch(logBits)
+ {
+ case LOG_INDENT : headerString += "> "; break;
+ case LOG_UNDENT : headerString += "< "; break;
+ case LOG_ALL : headerString += "A "; break;
+ case LOG_CRIT : headerString += "! "; break;
+ case LOG_DATA : headerString += "D "; break;
+ case LOG_ERR : headerString += "E "; break;
+ case LOG_FLOW : headerString += "F "; break;
+ case LOG_INFO : headerString += "I "; break;
+ case LOG_WARN : headerString += "W "; break;
+ default: headerString += " "; break;
+ }
+
+ // File string (strip out the path)
+
+ char temp[1024];
+ int ix = sourceFile().rfind('\\');
+ ix = (ix == (int) string::npos ? 0: ix+1);
+ sprintf(temp, "%25s[%04d]", sourceFile().substr(ix).c_str(), sourceLine());
+ headerString += temp;
+
+ // Time string (specially formatted to save room)
+
+ time_t t = time(NULL);
+ struct tm *tme = localtime(&t);
+ sprintf(temp, "%02d/%02d %02d:%02d ", tme->tm_mon + 1, tme->tm_mday, tme->tm_hour, tme->tm_min);
+ headerString += temp;
+
+ // Spaces for indentation
+
+ memset(temp, ' ', sizeof(temp));
+ temp[_indentCount] = '\0';
+
+ // Add the indentation markers
+
+ int count = 0;
+ while(count < _indentCount)
+ {
+ if (lineCharsFlag()) temp[count] = '\xB3';
+ else temp[count] = '|';
+ count += _indentChars;
+ }
+ headerString += temp;
+
+ return headerString;
+}
+
+#else /*Release Build*/
+ std::string release_Null;
+ void Logger::limitFileSize() const {}
+ const string &Logger::headerString(const LogFlags logBits) const{return release_Null;}
+ void Logger::start(const bool reset){}
+ void Logger::stop(){}
+ void Logger::logTex(const string &s, const LogFlags logBits /*= LOG_INFO*/){}
+ void Logger::logRaw(const string &s){}
+ void Logger::logHex(const char *buffer, const unsigned int count, const LogFlags logBits /*= LOG_INFO*/){}
+ void Logger::indent(const string &s, const LogFlags logBits /*= LOG_INDENT*/){}
+ void Logger::undent(const string &s, const LogFlags logBits /*= LOG_UNDENT*/){}
+#endif
+// ---------------------------------------------------------------------------------------------------------------------------------
+// logger.cpp - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _ _
+// | | | |
+// | | ___ __ _ __ _ ___ _ __ | |__
+// | |/ _ \ / _` |/ _` |/ _ \ '__| | '_ \
+// | | (_) | (_| | (_| | __/ | _ | | | |
+// |_|\___/ \__, |\__, |\___|_| (_)|_| |_|
+// __/ | __/ |
+// |___/ |___/
+//
+// Generic informational logging class
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 07/06/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifndef _H_LOGGER
+#define _H_LOGGER
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The global logger
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class Logger;
+extern Logger logger;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Macros (necessary evil to take advantage of __LINE__ and __FILE__)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#define LOG logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logTex
+#define HEX logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logHex
+#define RAW logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.logRaw
+#define INDENT logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.indent
+#define UNDENT logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__,logger.undent
+#define LOGBLOCK logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogBlock __lb__
+
+// If you compiler supports __FUNCTION__, then replace the "#if 1" with "#if 0". Note that this will change the usage of the macro
+
+#if 0
+#define LOGFUNC logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogFlow __lf__
+#else
+#define LOGFUNC logger.sourceLine() = __LINE__, logger.sourceFile() = __FILE__;LogFlow __lf__(__FUNCTION__)
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The logger class: does the actual logging
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class Logger
+{
+public:
+ // Enumerations
+
+ enum LogFlags
+ {
+ LOG_INDENT = 0x00000001,
+ LOG_UNDENT = 0x00000002,
+ LOG_FLOW = 0x00000004,
+ LOG_BLOK = 0x00000008,
+ LOG_DATA = 0x00000010,
+ LOG_INFO = 0x00000012,
+ LOG_WARN = 0x00000014,
+ LOG_ERR = 0x00000018,
+ LOG_CRIT = 0x00000020,
+ LOG_ALL = 0xFFFFFFFF
+ };
+
+ // Construction/Destruction
+
+inline Logger()
+ : _sourceLine(0), _indentCount(0), _indentChars(4), _fileSizeLimit(-1), _logMask(LOG_ALL),
+ _logStarted(false), _lineCharsFlag(false), _logFile("logger.log")
+ {
+ }
+
+virtual ~Logger()
+ {
+ stop();
+ }
+
+ // Operators
+
+inline void operator +=(const string &s) {logTex(s);}
+
+ // Accessors
+
+inline const bool &lineCharsFlag() const {return _lineCharsFlag;}
+inline bool &lineCharsFlag() {return _lineCharsFlag;}
+
+inline const int &fileSizeLimit() const {return _fileSizeLimit;}
+inline int &fileSizeLimit() {return _fileSizeLimit;}
+
+inline const unsigned int &logMask() const {return _logMask;}
+inline unsigned int &logMask() {return _logMask;}
+
+inline const string &logFile() const {return _logFile;}
+inline string &logFile() {return _logFile;}
+
+inline const unsigned int &sourceLine() const {return _sourceLine;}
+inline unsigned int &sourceLine() {return _sourceLine;}
+
+inline const string &sourceFile() const {return _sourceFile;}
+inline string &sourceFile() {return _sourceFile;}
+
+inline bool logStarted() const {return _logStarted;}
+
+ // Utilitarian (public)
+
+virtual void start(const bool reset);
+virtual void stop();
+virtual void logTex(const string &s, const LogFlags logBits = LOG_INFO);
+virtual void logRaw(const string &s);
+virtual void logHex(const char *buffer, const unsigned int count, const LogFlags logBits = LOG_INFO);
+virtual void indent(const string &s, const LogFlags logBits = LOG_INDENT);
+virtual void undent(const string &s, const LogFlags logBits = LOG_UNDENT);
+
+private:
+ // Utilitarian (private)
+
+virtual void limitFileSize() const;
+virtual const string &headerString(const LogFlags logBits) const;
+
+ // Data
+
+ string _logFile;
+ string _sourceFile;
+ unsigned int _sourceLine;
+ int _indentCount;
+ int _indentChars;
+ int _fileSizeLimit;
+ unsigned int _logMask;
+ bool _logStarted;
+ bool _lineCharsFlag;
+};
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The LogBlock class: used for automatic indentation
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class LogBlock
+{
+public:
+inline LogBlock(const string &s) {str = s;logger.indent("Begin block: " + str, Logger::LOG_INDENT);}
+inline ~LogBlock() {logger.undent("", Logger::LOG_UNDENT);}
+private:
+ string str;
+};
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The LogFlow class: used for logging code flow
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class LogFlow
+{
+public:
+inline LogFlow(const string &function) {str = function;logger.indent(str, Logger::LOG_FLOW);}
+inline ~LogFlow() {logger.undent("", Logger::LOG_FLOW);}
+private:
+ string str;
+};
+
+#endif // _H_LOGGER
+// ---------------------------------------------------------------------------------------------------------------------------------
+// logger.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
--- /dev/null
+// MD5.CC - source code for the C++/object oriented translation and
+// modification of MD5.
+
+// Translation and modification (c) 1995 by Mordechai T. Abzug
+
+// This translation/ modification is provided "as is," without express or
+// implied warranty of any kind.
+
+// The translator/ modifier does not claim (1) that MD5 will do what you think
+// it does; (2) that this translation/ modification is accurate; or (3) that
+// this software is "merchantible." (Language for this disclaimer partially
+// copied from the disclaimer below).
+
+/* based on:
+
+ MD5.H - header file for MD5C.C
+ MDDRIVER.C - test driver for MD2, MD4 and MD5
+
+ Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+
+*/
+
+#include <stdio.h>
+#include <fstream>
+#include <iostream>
+
+using namespace std;
+class MD5 {
+
+public:
+// methods for controlled operation:
+ MD5 (); // simple initializer
+ void update (unsigned char *input, unsigned int input_length);
+ void update (istream& stream);
+ void update (FILE *file);
+ void update (ifstream& stream);
+ void finalize ();
+
+// constructors for special circumstances. All these constructors finalize
+// the MD5 context.
+ MD5 (unsigned char *string); // digest string, finalize
+ MD5 (istream& stream); // digest stream, finalize
+ MD5 (FILE *file); // digest file, close, finalize
+ MD5 (ifstream& stream); // digest stream, close, finalize
+
+// methods to acquire finalized result
+ unsigned char *raw_digest (); // digest as a 16-byte binary array
+ char * hex_digest (); // digest as a 33-byte ascii-hex string
+ friend ostream& operator<< (ostream&, MD5 context);
+
+
+
+private:
+
+// first, some types:
+ typedef unsigned int uint4; // assumes integer is 4 words long
+ typedef unsigned short int uint2; // assumes short integer is 2 words long
+ typedef unsigned char uint1; // assumes char is 1 word long
+
+// next, the private data:
+ uint4 state[4];
+ uint4 count[2]; // number of *bits*, mod 2^64
+ uint1 buffer[64]; // input buffer
+ uint1 digest[16];
+ uint1 finalized;
+
+// last, the private methods, mostly static:
+ void init (); // called by all constructors
+ void transform (uint1 *buffer); // does the real update work. Note
+ // that length is implied to be 64.
+
+ static void encode (uint1 *dest, uint4 *src, uint4 length);
+ static void decode (uint4 *dest, uint1 *src, uint4 length);
+ static void memcpy (uint1 *dest, uint1 *src, uint4 length);
+ static void memset (uint1 *start, uint1 val, uint4 length);
+
+ static inline uint4 rotate_left (uint4 x, uint4 n);
+ static inline uint4 F (uint4 x, uint4 y, uint4 z);
+ static inline uint4 G (uint4 x, uint4 y, uint4 z);
+ static inline uint4 H (uint4 x, uint4 y, uint4 z);
+ static inline uint4 I (uint4 x, uint4 y, uint4 z);
+ static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac);
+ static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac);
+ static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac);
+ static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
+ uint4 s, uint4 ac);
+
+};
\ No newline at end of file
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+//
+// _ __ ___ _ __ ___ __ _ _ __ ___ _ __ _ __
+// | '_ ` _ \| '_ ` _ \ / _` | '__| / __| '_ \| '_ \
+// | | | | | | | | | | | (_| | | _ | (__| |_) | |_) |
+// |_| |_| |_|_| |_| |_|\__, |_| (_) \___| .__/| .__/
+// __/ | | | | |
+// |___/ |_| |_|
+//
+// Memory manager & tracking software
+//
+// Best viewed with 8-character tabs and (at least) 132 columns
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 12/22/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// !!IMPORTANT!!
+//
+// This software is self-documented with periodic comments. Before you start using this software, perform a search for the string
+// "-DOC-" to locate pertinent information about how to use this software.
+//
+// You are also encouraged to read the comment blocks throughout this source file. They will help you understand how this memory
+// tracking software works, so you can better utilize it within your applications.
+//
+// NOTES:
+//
+// 1. If you get compiler errors having to do with set_new_handler, then go through this source and search/replace
+// "std::set_new_handler" with "set_new_handler".
+//
+// 2. This code purposely uses no external routines that allocate RAM (other than the raw allocation routines, such as malloc). We
+// do this because we want this to be as self-contained as possible. As an example, we don't use assert, because when running
+// under WIN32, the assert brings up a dialog box, which allocates RAM. Doing this in the middle of an allocation would be bad.
+//
+// 3. When trying to override new/delete under MFC (which has its own version of global new/delete) the linker will complain. In
+// order to fix this error, use the compiler option: /FORCE, which will force it to build an executable even with linker errors.
+// Be sure to check those errors each time you compile, otherwise, you may miss a valid linker error.
+//
+// 4. If you see something that looks odd to you or seems like a strange way of going about doing something, then consider that this
+// code was carefully thought out. If something looks odd, then just assume I've got a good reason for doing it that way (an
+// example is the use of the class MemStaticTimeTracker.)
+//
+// 5. With MFC applications, you will need to comment out any occurance of "#define new DEBUG_NEW" from all source files.
+//
+// 6. Include file dependencies are _very_important_ for getting the MMGR to integrate nicely into your application. Be careful if
+// you're including standard includes from within your own project inclues; that will break this very specific dependency order.
+// It should look like this:
+//
+// #include <stdio.h> // Standard includes MUST come first
+// #include <stdlib.h> //
+// #include <streamio> //
+//
+// #include "mmgr.h" // mmgr.h MUST come next
+//
+// #include "myfile1.h" // Project includes MUST come last
+// #include "myfile2.h" //
+// #include "myfile3.h" //
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <new>
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#include "mmgr.h"
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- If you're like me, it's hard to gain trust in foreign code. This memory manager will try to INDUCE your code to crash (for
+// very good reasons... like making bugs obvious as early as possible.) Some people may be inclined to remove this memory tracking
+// software if it causes crashes that didn't exist previously. In reality, these new crashes are the BEST reason for using this
+// software!
+//
+// Whether this software causes your application to crash, or if it reports errors, you need to be able to TRUST this software. To
+// this end, you are given some very simple debugging tools.
+//
+// The quickest way to locate problems is to enable the STRESS_TEST macro (below.) This should catch 95% of the crashes before they
+// occur by validating every allocation each time this memory manager performs an allocation function. If that doesn't work, keep
+// reading...
+//
+// If you enable the TEST_MEMORY_MANAGER #define (below), this memory manager will log an entry in the memory.log file each time it
+// enters and exits one of its primary allocation handling routines. Each call that succeeds should place an "ENTER" and an "EXIT"
+// into the log. If the program crashes within the memory manager, it will log an "ENTER", but not an "EXIT". The log will also
+// report the name of the routine.
+//
+// Just because this memory manager crashes does not mean that there is a bug here! First, an application could inadvertantly damage
+// the heap, causing malloc(), realloc() or free() to crash. Also, an application could inadvertantly damage some of the memory used
+// by this memory tracking software, causing it to crash in much the same way that a damaged heap would affect the standard
+// allocation routines.
+//
+// In the event of a crash within this code, the first thing you'll want to do is to locate the actual line of code that is
+// crashing. You can do this by adding log() entries throughout the routine that crashes, repeating this process until you narrow
+// in on the offending line of code. If the crash happens in a standard C allocation routine (i.e. malloc, realloc or free) don't
+// bother contacting me, your application has damaged the heap. You can help find the culprit in your code by enabling the
+// STRESS_TEST macro (below.)
+//
+// If you truely suspect a bug in this memory manager (and you had better be sure about it! :) you can contact me at
+// midnight@FluidStudios.com. Before you do, however, check for a newer version at:
+//
+// http://www.FluidStudios.com/publications.html
+//
+// When using this debugging aid, make sure that you are NOT setting the alwaysLogAll variable on, otherwise the log could be
+// cluttered and hard to read.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define TEST_MEMORY_MANAGER
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Enable this sucker if you really want to stress-test your app's memory usage, or to help find hard-to-find bugs
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define STRESS_TEST
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Enable this sucker if you want to stress-test your app's error-handling. Set RANDOM_FAIL to the percentage of failures you
+// want to test with (0 = none, >100 = all failures).
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define RANDOM_FAILURE 10.0
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Locals -- modify these flags to suit your needs
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifdef STRESS_TEST
+static const unsigned int hashBits = 12;
+static bool randomWipe = true;
+static bool alwaysValidateAll = true;
+static bool alwaysLogAll = true;
+static bool alwaysWipeAll = true;
+static bool cleanupLogOnFirstRun = true;
+static const unsigned int paddingSize = 1024; // An extra 8K per allocation!
+#else
+static const unsigned int hashBits = 12;
+static bool randomWipe = false;
+static bool alwaysValidateAll = false;
+static bool alwaysLogAll = false;
+static bool alwaysWipeAll = true;
+static bool cleanupLogOnFirstRun = true;
+static const unsigned int paddingSize = 4;
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// We define our own assert, because we don't want to bring up an assertion dialog, since that allocates RAM. Our new assert
+// simply declares a forced breakpoint.
+//
+// The BEOS assert added by Arvid Norberg <arvid@iname.com>.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifdef WIN32
+ #ifdef _DEBUG
+ #define m_assert(x) if ((x) == false) __asm { int 3 }
+ #else
+ #define m_assert(x) {}
+ #endif
+#elif defined(__BEOS__)
+ #ifdef DEBUG
+ extern void debugger(const char *message);
+ #define m_assert(x) if ((x) == false) debugger("mmgr: assert failed")
+ #else
+ #define m_assert(x) {}
+ #endif
+#else // Linux uses assert, which we can use safely, since it doesn't bring up a dialog within the program.
+ #define m_assert(cond) assert(cond)
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Here, we turn off our macros because any place in this source file where the word 'new' or the word 'delete' (etc.)
+// appear will be expanded by the macro. So to avoid problems using them within this source file, we'll just #undef them.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#undef new
+#undef delete
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Defaults for the constants & statics in the MemoryManager class
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+const unsigned int m_alloc_unknown = 0;
+const unsigned int m_alloc_new = 1;
+const unsigned int m_alloc_new_array = 2;
+const unsigned int m_alloc_malloc = 3;
+const unsigned int m_alloc_calloc = 4;
+const unsigned int m_alloc_realloc = 5;
+const unsigned int m_alloc_delete = 6;
+const unsigned int m_alloc_delete_array = 7;
+const unsigned int m_alloc_free = 8;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Get to know these values. They represent the values that will be used to fill unused and deallocated RAM.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static unsigned int prefixPattern = 0xbaadf00d; // Fill pattern for bytes preceeding allocated blocks
+static unsigned int postfixPattern = 0xdeadc0de; // Fill pattern for bytes following allocated blocks
+static unsigned int unusedPattern = 0xfeedface; // Fill pattern for freshly allocated blocks
+static unsigned int releasedPattern = 0xdeadbeef; // Fill pattern for deallocated blocks
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Other locals
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static const unsigned int hashSize = 1 << hashBits;
+static const char *allocationTypes[] = {"Unknown",
+ "new", "new[]", "malloc", "calloc",
+ "realloc", "delete", "delete[]", "free"};
+static sAllocUnit *hashTable[hashSize];
+static sAllocUnit *reservoir;
+static unsigned int currentAllocationCount = 0;
+static unsigned int breakOnAllocationCount = 0;
+static sMStats stats;
+static const char *sourceFile = "??";
+static const char *sourceFunc = "??";
+static unsigned int sourceLine = 0;
+static bool staticDeinitTime = false;
+static sAllocUnit **reservoirBuffer = NULL;
+static unsigned int reservoirBufferSize = 0;
+static const char *memoryLogFile = "memory.log";
+static const char *memoryLeakLogFile = "memleaks.log";
+static void doCleanupLogOnFirstRun();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Local functions only
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void log(const char *format, ...)
+{
+ // Cleanup the log?
+
+ if (cleanupLogOnFirstRun) doCleanupLogOnFirstRun();
+
+ // Build the buffer
+
+ static char buffer[2048];
+ va_list ap;
+ va_start(ap, format);
+ vsprintf(buffer, format, ap);
+ va_end(ap);
+
+ // Open the log file
+
+ FILE *fp = fopen(memoryLogFile, "ab");
+
+ // If you hit this assert, then the memory logger is unable to log information to a file (can't open the file for some
+ // reason.) You can interrogate the variable 'buffer' to see what was supposed to be logged (but won't be.)
+ m_assert(fp);
+
+ if (!fp) return;
+
+ // Spit out the data to the log
+
+ fprintf(fp, "%s\r\n", buffer);
+ fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void doCleanupLogOnFirstRun()
+{
+ if (cleanupLogOnFirstRun)
+ {
+ unlink(memoryLogFile);
+ cleanupLogOnFirstRun = false;
+
+ // Print a header for the log
+
+ time_t t = time(NULL);
+ log("--------------------------------------------------------------------------------");
+ log("");
+ log(" %s - Memory logging file created on %s", memoryLogFile, asctime(localtime(&t)));
+ log("--------------------------------------------------------------------------------");
+ log("");
+ log("This file contains a log of all memory operations performed during the last run.");
+ log("");
+ log("Interrogate this file to track errors or to help track down memory-related");
+ log("issues. You can do this by tracing the allocations performed by a specific owner");
+ log("or by tracking a specific address through a series of allocations and");
+ log("reallocations.");
+ log("");
+ log("There is a lot of useful information here which, when used creatively, can be");
+ log("extremely helpful.");
+ log("");
+ log("Note that the following guides are used throughout this file:");
+ log("");
+ log(" [!] - Error");
+ log(" [+] - Allocation");
+ log(" [~] - Reallocation");
+ log(" [-] - Deallocation");
+ log(" [I] - Generic information");
+ log(" [F] - Failure induced for the purpose of stress-testing your application");
+ log(" [D] - Information used for debugging this memory manager");
+ log("");
+ log("...so, to find all errors in the file, search for \"[!]\"");
+ log("");
+ log("--------------------------------------------------------------------------------");
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static const char *sourceFileStripper(const char *sourceFile)
+{
+ char *ptr = strrchr(sourceFile, '\\');
+ if (ptr) return ptr + 1;
+ ptr = strrchr(sourceFile, '/');
+ if (ptr) return ptr + 1;
+ return sourceFile;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static const char *ownerString(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc)
+{
+ static char str[90];
+ memset(str, 0, sizeof(str));
+ sprintf(str, "%s(%05d)::%s", sourceFileStripper(sourceFile), sourceLine, sourceFunc);
+ return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static const char *insertCommas(unsigned int value)
+{
+ static char str[30];
+ memset(str, 0, sizeof(str));
+
+ sprintf(str, "%u", value);
+ if (strlen(str) > 3)
+ {
+ memmove(&str[strlen(str)-3], &str[strlen(str)-4], 4);
+ str[strlen(str) - 4] = ',';
+ }
+ if (strlen(str) > 7)
+ {
+ memmove(&str[strlen(str)-7], &str[strlen(str)-8], 8);
+ str[strlen(str) - 8] = ',';
+ }
+ if (strlen(str) > 11)
+ {
+ memmove(&str[strlen(str)-11], &str[strlen(str)-12], 12);
+ str[strlen(str) - 12] = ',';
+ }
+
+ return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static const char *memorySizeString(unsigned long size)
+{
+ static char str[90];
+ if (size > (1024*1024)) sprintf(str, "%10s (%7.2fM)", insertCommas(size), static_cast<float>(size) / (1024.0f * 1024.0f));
+ else if (size > 1024) sprintf(str, "%10s (%7.2fK)", insertCommas(size), static_cast<float>(size) / 1024.0f);
+ else sprintf(str, "%10s bytes ", insertCommas(size));
+ return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static sAllocUnit *findAllocUnit(const void *reportedAddress)
+{
+ // Just in case...
+ m_assert(reportedAddress != NULL);
+
+ // Use the address to locate the hash index. Note that we shift off the lower four bits. This is because most allocated
+ // addresses will be on four-, eight- or even sixteen-byte boundaries. If we didn't do this, the hash index would not have
+ // very good coverage.
+
+ unsigned int hashIndex = (reinterpret_cast<unsigned int>(const_cast<void *>(reportedAddress)) >> 4) & (hashSize - 1);
+ sAllocUnit *ptr = hashTable[hashIndex];
+ while(ptr)
+ {
+ if (ptr->reportedAddress == reportedAddress) return ptr;
+ ptr = ptr->next;
+ }
+
+ return NULL;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static size_t calculateActualSize(const size_t reportedSize)
+{
+ // We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as
+ // being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's
+ // 8 bytes, which means an int can actually be larger than a long.)
+
+ return reportedSize + paddingSize * sizeof(long) * 2;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static size_t calculateReportedSize(const size_t actualSize)
+{
+ // We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as
+ // being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's
+ // 8 bytes, which means an int can actually be larger than a long.)
+
+ return actualSize - paddingSize * sizeof(long) * 2;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void *calculateReportedAddress(const void *actualAddress)
+{
+ // We allow this...
+
+ if (!actualAddress) return NULL;
+
+ // JUst account for the padding
+
+ return reinterpret_cast<void *>(const_cast<char *>(reinterpret_cast<const char *>(actualAddress) + sizeof(long) * paddingSize));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void wipeWithPattern(sAllocUnit *allocUnit, unsigned long pattern, const unsigned int originalReportedSize = 0)
+{
+ // For a serious test run, we use wipes of random a random value. However, if this causes a crash, we don't want it to
+ // crash in a differnt place each time, so we specifically DO NOT call srand. If, by chance your program calls srand(),
+ // you may wish to disable that when running with a random wipe test. This will make any crashes more consistent so they
+ // can be tracked down easier.
+
+ if (randomWipe)
+ {
+ pattern = ((rand() & 0xff) << 24) | ((rand() & 0xff) << 16) | ((rand() & 0xff) << 8) | (rand() & 0xff);
+ }
+
+ // -DOC- We should wipe with 0's if we're not in debug mode, so we can help hide bugs if possible when we release the
+ // product. So uncomment the following line for releases.
+ //
+ // Note that the "alwaysWipeAll" should be turned on for this to have effect, otherwise it won't do much good. But we'll
+ // leave it this way (as an option) because this does slow things down.
+// pattern = 0;
+
+ // This part of the operation is optional
+
+ if (alwaysWipeAll && allocUnit->reportedSize > originalReportedSize)
+ {
+ // Fill the bulk
+
+ long *lptr = reinterpret_cast<long *>(reinterpret_cast<char *>(allocUnit->reportedAddress) + originalReportedSize);
+ int length = static_cast<int>(allocUnit->reportedSize - originalReportedSize);
+ int i;
+ for (i = 0; i < (length >> 2); i++, lptr++)
+ {
+ *lptr = pattern;
+ }
+
+ // Fill the remainder
+
+ unsigned int shiftCount = 0;
+ char *cptr = reinterpret_cast<char *>(lptr);
+ for (i = 0; i < (length & 0x3); i++, cptr++, shiftCount += 8)
+ {
+ *cptr = static_cast<char>((pattern & (0xff << shiftCount)) >> shiftCount);
+ }
+ }
+
+ // Write in the prefix/postfix bytes
+
+ long *pre = reinterpret_cast<long *>(allocUnit->actualAddress);
+ long *post = reinterpret_cast<long *>(reinterpret_cast<char *>(allocUnit->actualAddress) + allocUnit->actualSize - paddingSize * sizeof(long));
+ for (unsigned int i = 0; i < paddingSize; i++, pre++, post++)
+ {
+ *pre = prefixPattern;
+ *post = postfixPattern;
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void dumpAllocations(FILE *fp)
+{
+ fprintf(fp, "Alloc. Addr Size Addr Size BreakOn BreakOn \r\n");
+ fprintf(fp, "Number Reported Reported Actual Actual Unused Method Dealloc Realloc Allocated by \r\n");
+ fprintf(fp, "------ ---------- ---------- ---------- ---------- ---------- -------- ------- ------- --------------------------------------------------- \r\n");
+
+
+ for (unsigned int i = 0; i < hashSize; i++)
+ {
+ sAllocUnit *ptr = hashTable[i];
+ while(ptr)
+ {
+ fprintf(fp, "%06d 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X %-8s %c %c %s\r\n",
+ ptr->allocationNumber,
+ reinterpret_cast<unsigned int>(ptr->reportedAddress), ptr->reportedSize,
+ reinterpret_cast<unsigned int>(ptr->actualAddress), ptr->actualSize,
+ m_calcUnused(ptr),
+ allocationTypes[ptr->allocationType],
+ ptr->breakOnDealloc ? 'Y':'N',
+ ptr->breakOnRealloc ? 'Y':'N',
+ ownerString(ptr->sourceFile, ptr->sourceLine, ptr->sourceFunc));
+ ptr = ptr->next;
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void dumpLeakReport()
+{
+ // Open the report file
+
+ FILE *fp = fopen(memoryLeakLogFile, "w+b");
+
+ // If you hit this assert, then the memory report generator is unable to log information to a file (can't open the file for
+ // some reason.)
+ m_assert(fp);
+ if (!fp) return;
+
+ // Any leaks?
+
+ // Header
+
+ static char timeString[25];
+ memset(timeString, 0, sizeof(timeString));
+ time_t t = time(NULL);
+ struct tm *tme = localtime(&t);
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| Memory leak report for: %02d/%02d/%04d %02d:%02d:%02d |\r\n", tme->tm_mon + 1, tme->tm_mday, tme->tm_year + 1900, tme->tm_hour, tme->tm_min, tme->tm_sec);
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "\r\n");
+ fprintf(fp, "\r\n");
+ if (stats.totalAllocUnitCount)
+ {
+ fprintf(fp, "%d memory leak%s found:\r\n", stats.totalAllocUnitCount, stats.totalAllocUnitCount == 1 ? "":"s");
+ }
+ else
+ {
+ fprintf(fp, "Congratulations! No memory leaks found!\r\n");
+
+ // We can finally free up our own memory allocations
+
+ if (reservoirBuffer)
+ {
+ for (unsigned int i = 0; i < reservoirBufferSize; i++)
+ {
+ free(reservoirBuffer[i]);
+ }
+ free(reservoirBuffer);
+ reservoirBuffer = 0;
+ reservoirBufferSize = 0;
+ reservoir = NULL;
+ }
+ }
+ fprintf(fp, "\r\n");
+
+ if (stats.totalAllocUnitCount)
+ {
+ dumpAllocations(fp);
+ }
+
+ fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// We use a static class to let us know when we're in the midst of static deinitialization
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class MemStaticTimeTracker
+{
+public:
+ MemStaticTimeTracker() {doCleanupLogOnFirstRun();}
+ ~MemStaticTimeTracker() {staticDeinitTime = true; dumpLeakReport();}
+};
+static MemStaticTimeTracker mstt;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Flags & options -- Call these routines to enable/disable the following options
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_alwaysValidateAll()
+{
+ // Force a validation of all allocation units each time we enter this software
+ return alwaysValidateAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_alwaysLogAll()
+{
+ // Force a log of every allocation & deallocation into memory.log
+ return alwaysLogAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_alwaysWipeAll()
+{
+ // Force this software to always wipe memory with a pattern when it is being allocated/dallocated
+ return alwaysWipeAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_randomeWipe()
+{
+ // Force this software to use a random pattern when wiping memory -- good for stress testing
+ return randomWipe;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is
+// reallocated.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_breakOnRealloc(void *reportedAddress)
+{
+ // Locate the existing allocation unit
+
+ sAllocUnit *au = findAllocUnit(reportedAddress);
+
+ // If you hit this assert, you tried to set a breakpoint on reallocation for an address that doesn't exist. Interrogate the
+ // stack frame or the variable 'au' to see which allocation this is.
+ m_assert(au != NULL);
+
+ // If you hit this assert, you tried to set a breakpoint on reallocation for an address that wasn't allocated in a way that
+ // is compatible with reallocation.
+ m_assert(au->allocationType == m_alloc_malloc ||
+ au->allocationType == m_alloc_calloc ||
+ au->allocationType == m_alloc_realloc);
+
+ return au->breakOnRealloc;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is
+// deallocated.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_breakOnDealloc(void *reportedAddress)
+{
+ // Locate the existing allocation unit
+
+ sAllocUnit *au = findAllocUnit(reportedAddress);
+
+ // If you hit this assert, you tried to set a breakpoint on deallocation for an address that doesn't exist. Interrogate the
+ // stack frame or the variable 'au' to see which allocation this is.
+ m_assert(au != NULL);
+
+ return au->breakOnDealloc;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- When tracking down a difficult bug, use this routine to force a breakpoint on a specific allocation count
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_breakOnAllocation(unsigned int count)
+{
+ breakOnAllocationCount = count;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Used by the macros
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_setOwner(const char *file, const unsigned int line, const char *func)
+{
+ // You're probably wondering about this...
+ //
+ // It's important for this memory manager to primarily work with global new/delete in their original forms (i.e. with
+ // no extra parameters.) In order to do this, we use macros that call this function prior to operators new & delete. This
+ // is fine... usually. Here's what actually happens when you use this macro to delete an object:
+ //
+ // m_setOwner(__FILE__, __LINE__, __FUNCTION__) --> object::~object() --> delete
+ //
+ // Note that the compiler inserts a call to the object's destructor just prior to calling our overridden operator delete.
+ // But what happens when we delete an object whose destructor deletes another object, whose desctuctor deletes another
+ // object? Here's a diagram (indentation follows stack depth):
+ //
+ // m_setOwner(...) -> ~obj1() // original call to delete obj1
+ // m_setOwner(...) -> ~obj2() // obj1's destructor deletes obj2
+ // m_setOwner(...) -> ~obj3() // obj2's destructor deletes obj3
+ // ... // obj3's destructor just does some stuff
+ // delete // back in obj2's destructor, we call delete
+ // delete // back in obj1's destructor, we call delete
+ // delete // back to our original call, we call delete
+ //
+ // Because m_setOwner() just sets up some static variables (below) it's important that each call to m_setOwner() and
+ // successive calls to new/delete alternate. However, in this case, three calls to m_setOwner() happen in succession
+ // followed by three calls to delete in succession (with a few calls to destructors mixed in for fun.) This means that
+ // only the final call to delete (in this chain of events) will have the proper reporting, and the first two in the chain
+ // will not have ANY owner-reporting information. The deletes will still work fine, we just won't know who called us.
+ //
+ // "Then build a stack, my friend!" you might think... but it's a very common thing that people will be working with third-
+ // party libraries (including MFC under Windows) which is not compiled with this memory manager's macros. In those cases,
+ // m_setOwner() is never called, and rightfully should not have the proper trace-back information. So if one of the
+ // destructors in the chain ends up being a call to a delete from a non-mmgr-compiled library, the stack will get confused.
+ //
+ // I've been unable to find a solution to this problem, but at least we can detect it and report the data before we
+ // lose it. That's what this is all about. It makes it somewhat confusing to read in the logs, but at least ALL the
+ // information is present...
+ //
+ // There's a caveat here... The compiler is not required to call operator delete if the value being deleted is NULL.
+ // In this case, any call to delete with a NULL will sill call m_setOwner(), which will make m_setOwner() think that
+ // there is a destructor chain becuase we setup the variables, but nothing gets called to clear them. Because of this
+ // we report a "Possible destructor chain".
+ //
+ // Thanks to J. Woznack (from Kodiak Interactive Software Studios -- www.kodiakgames.com) for pointing this out.
+
+ if (sourceLine && alwaysLogAll)
+ {
+ log("[I] NOTE! Possible destructor chain: previous owner is %s", ownerString(sourceFile, sourceLine, sourceFunc));
+ }
+
+ // Okay... save this stuff off so we can keep track of the caller
+
+ sourceFile = file;
+ sourceLine = line;
+ sourceFunc = func;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static void resetGlobals()
+{
+ sourceFile = "??";
+ sourceLine = 0;
+ sourceFunc = "??";
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Global new/new[]
+//
+// These are the standard new/new[] operators. They are merely interface functions that operate like normal new/new[], but use our
+// memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *operator new(size_t reportedSize)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: new");
+ #endif
+
+ // Save these off...
+
+ const char *file = sourceFile;
+ const unsigned int line = sourceLine;
+ const char *func = sourceFunc;
+
+ // ANSI says: allocation requests of 0 bytes will still return a valid value
+
+ if (reportedSize == 0) reportedSize = 1;
+
+ // ANSI says: loop continuously because the error handler could possibly free up some memory
+
+ for(;;)
+ {
+ // Try the allocation
+
+ void *ptr = m_allocator(file, line, func, m_alloc_new, reportedSize);
+ if (ptr)
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new");
+ #endif
+ return ptr;
+ }
+
+ // There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+ // set it back again.
+
+ std::new_handler nh = std::set_new_handler(0);
+ std::set_new_handler(nh);
+
+ // If there is an error handler, call it
+
+ if (nh)
+ {
+ (*nh)();
+ }
+
+ // Otherwise, throw the exception
+
+ else
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new");
+ #endif
+ throw std::bad_alloc();
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *operator new[](size_t reportedSize)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: new[]");
+ #endif
+
+ // Save these off...
+
+ const char *file = sourceFile;
+ const unsigned int line = sourceLine;
+ const char *func = sourceFunc;
+
+ // The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+ if (reportedSize == 0) reportedSize = 1;
+
+ // ANSI says: loop continuously because the error handler could possibly free up some memory
+
+ for(;;)
+ {
+ // Try the allocation
+
+ void *ptr = m_allocator(file, line, func, m_alloc_new_array, reportedSize);
+ if (ptr)
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new[]");
+ #endif
+ return ptr;
+ }
+
+ // There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+ // set it back again.
+
+ std::new_handler nh = std::set_new_handler(0);
+ std::set_new_handler(nh);
+
+ // If there is an error handler, call it
+
+ if (nh)
+ {
+ (*nh)();
+ }
+
+ // Otherwise, throw the exception
+
+ else
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new[]");
+ #endif
+ throw std::bad_alloc();
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Other global new/new[]
+//
+// These are the standard new/new[] operators as used by Microsoft's memory tracker. We don't want them interfering with our memory
+// tracking efforts. Like the previous versions, these are merely interface functions that operate like normal new/new[], but use
+// our memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *operator new(size_t reportedSize, const char *sourceFile, int sourceLine)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: new");
+ #endif
+
+ // The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+ if (reportedSize == 0) reportedSize = 1;
+
+ // ANSI says: loop continuously because the error handler could possibly free up some memory
+
+ for(;;)
+ {
+ // Try the allocation
+
+ void *ptr = m_allocator(sourceFile, sourceLine, "??", m_alloc_new, reportedSize);
+ if (ptr)
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new");
+ #endif
+ return ptr;
+ }
+
+ // There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+ // set it back again.
+
+ std::new_handler nh = std::set_new_handler(0);
+ std::set_new_handler(nh);
+
+ // If there is an error handler, call it
+
+ if (nh)
+ {
+ (*nh)();
+ }
+
+ // Otherwise, throw the exception
+
+ else
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new");
+ #endif
+ throw std::bad_alloc();
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *operator new[](size_t reportedSize, const char *sourceFile, int sourceLine)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: new[]");
+ #endif
+
+ // The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+ if (reportedSize == 0) reportedSize = 1;
+
+ // ANSI says: loop continuously because the error handler could possibly free up some memory
+
+ for(;;)
+ {
+ // Try the allocation
+
+ void *ptr = m_allocator(sourceFile, sourceLine, "??", m_alloc_new_array, reportedSize);
+ if (ptr)
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new[]");
+ #endif
+ return ptr;
+ }
+
+ // There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+ // set it back again.
+
+ std::new_handler nh = std::set_new_handler(0);
+ std::set_new_handler(nh);
+
+ // If there is an error handler, call it
+
+ if (nh)
+ {
+ (*nh)();
+ }
+
+ // Otherwise, throw the exception
+
+ else
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : new[]");
+ #endif
+ throw std::bad_alloc();
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Global delete/delete[]
+//
+// These are the standard delete/delete[] operators. They are merely interface functions that operate like normal delete/delete[],
+// but use our memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void operator delete(void *reportedAddress)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: delete");
+ #endif
+
+ // ANSI says: delete & delete[] allow NULL pointers (they do nothing)
+
+ if (reportedAddress) m_deallocator(sourceFile, sourceLine, sourceFunc, m_alloc_delete, reportedAddress);
+ else if (alwaysLogAll) log("[-] ----- %8s of NULL by %s", allocationTypes[m_alloc_delete], ownerString(sourceFile, sourceLine, sourceFunc));
+
+ // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+ // source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+ resetGlobals();
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : delete");
+ #endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void operator delete[](void *reportedAddress)
+{
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: delete[]");
+ #endif
+
+ // ANSI says: delete & delete[] allow NULL pointers (they do nothing)
+
+ if (reportedAddress) m_deallocator(sourceFile, sourceLine, sourceFunc, m_alloc_delete_array, reportedAddress);
+ else if (alwaysLogAll)
+ log("[-] ----- %8s of NULL by %s", allocationTypes[m_alloc_delete_array], ownerString(sourceFile, sourceLine, sourceFunc));
+
+ // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+ // source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+ resetGlobals();
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : delete[]");
+ #endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Allocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *m_allocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int allocationType, const size_t reportedSize)
+{
+ try
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: m_allocator()");
+ #endif
+
+ // Increase our allocation count
+
+ currentAllocationCount++;
+
+ // Log the request
+
+ if (alwaysLogAll) log("[+] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[allocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc));
+
+ // If you hit this assert, you requested a breakpoint on a specific allocation count
+ m_assert(currentAllocationCount != breakOnAllocationCount);
+
+ // If necessary, grow the reservoir of unused allocation units
+
+ if (!reservoir)
+ {
+ // Allocate 256 reservoir elements
+
+ reservoir = (sAllocUnit *) malloc(sizeof(sAllocUnit) * 256);
+
+ // If you hit this assert, then the memory manager failed to allocate internal memory for tracking the
+ // allocations
+ m_assert(reservoir != NULL);
+
+ // Danger Will Robinson!
+
+ if (reservoir == NULL) throw "Unable to allocate RAM for internal memory tracking data";
+
+ // Build a linked-list of the elements in our reservoir
+
+ memset(reservoir, 0, sizeof(sAllocUnit) * 256);
+ for (unsigned int i = 0; i < 256 - 1; i++)
+ {
+ reservoir[i].next = &reservoir[i+1];
+ }
+
+ // Add this address to our reservoirBuffer so we can free it later
+
+ sAllocUnit **temp = (sAllocUnit **) realloc(reservoirBuffer, (reservoirBufferSize + 1) * sizeof(sAllocUnit *));
+ m_assert(temp);
+ if (temp)
+ {
+ reservoirBuffer = temp;
+ reservoirBuffer[reservoirBufferSize++] = reservoir;
+ }
+ }
+
+ // Logical flow says this should never happen...
+ m_assert(reservoir != NULL);
+
+ // Grab a new allocaton unit from the front of the reservoir
+
+ sAllocUnit *au = reservoir;
+ reservoir = au->next;
+
+ // Populate it with some real data
+
+ memset(au, 0, sizeof(sAllocUnit));
+ au->actualSize = calculateActualSize(reportedSize);
+ #ifdef RANDOM_FAILURE
+ double a = rand();
+ double b = RAND_MAX / 100.0 * RANDOM_FAILURE;
+ if (a > b)
+ {
+ au->actualAddress = malloc(au->actualSize);
+ }
+ else
+ {
+ log("[F] Random faiure");
+ au->actualAddress = NULL;
+ }
+ #else
+ au->actualAddress = malloc(au->actualSize);
+ #endif
+ au->reportedSize = reportedSize;
+ au->reportedAddress = calculateReportedAddress(au->actualAddress);
+ au->allocationType = allocationType;
+ au->sourceLine = sourceLine;
+ au->allocationNumber = currentAllocationCount;
+ if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1);
+ else strcpy (au->sourceFile, "??");
+ if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1);
+ else strcpy (au->sourceFunc, "??");
+
+ // We don't want to assert with random failures, because we want the application to deal with them.
+
+ #ifndef RANDOM_FAILURE
+ // If you hit this assert, then the requested allocation simply failed (you're out of memory.) Interrogate the
+ // variable 'au' or the stack frame to see what you were trying to do.
+ m_assert(au->actualAddress != NULL);
+ #endif
+
+ if (au->actualAddress == NULL)
+ {
+ throw "Request for allocation failed. Out of memory.";
+ }
+
+ // If you hit this assert, then this allocation was made from a source that isn't setup to use this memory tracking
+ // software, use the stack frame to locate the source and include our H file.
+ m_assert(allocationType != m_alloc_unknown);
+
+ // Insert the new allocation into the hash table
+
+ unsigned int hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+ if (hashTable[hashIndex]) hashTable[hashIndex]->prev = au;
+ au->next = hashTable[hashIndex];
+ au->prev = NULL;
+ hashTable[hashIndex] = au;
+
+ // Account for the new allocatin unit in our stats
+
+ stats.totalReportedMemory += static_cast<unsigned int>(au->reportedSize);
+ stats.totalActualMemory += static_cast<unsigned int>(au->actualSize);
+ stats.totalAllocUnitCount++;
+ if (stats.totalReportedMemory > stats.peakReportedMemory) stats.peakReportedMemory = stats.totalReportedMemory;
+ if (stats.totalActualMemory > stats.peakActualMemory) stats.peakActualMemory = stats.totalActualMemory;
+ if (stats.totalAllocUnitCount > stats.peakAllocUnitCount) stats.peakAllocUnitCount = stats.totalAllocUnitCount;
+ stats.accumulatedReportedMemory += static_cast<unsigned int>(au->reportedSize);
+ stats.accumulatedActualMemory += static_cast<unsigned int>(au->actualSize);
+ stats.accumulatedAllocUnitCount++;
+
+ // Prepare the allocation unit for use (wipe it with recognizable garbage)
+
+ wipeWithPattern(au, unusedPattern);
+
+ // calloc() expects the reported memory address range to be filled with 0's
+
+ if (allocationType == m_alloc_calloc)
+ {
+ memset(au->reportedAddress, 0, au->reportedSize);
+ }
+
+ // Validate every single allocated unit in memory
+
+ if (alwaysValidateAll) m_validateAllAllocUnits();
+
+ // Log the result
+
+ if (alwaysLogAll) log("[+] ----> addr 0x%08X", reinterpret_cast<unsigned int>(au->reportedAddress));
+
+ // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+ // source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+ resetGlobals();
+
+ // Return the (reported) address of the new allocation unit
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : m_allocator()");
+ #endif
+
+ return au->reportedAddress;
+ }
+ catch(const char *err)
+ {
+ // Deal with the errors
+
+ log("[!] %s", err);
+ resetGlobals();
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : m_allocator()");
+ #endif
+
+ return NULL;
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Reallocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *m_reallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int reallocationType, const size_t reportedSize, void *reportedAddress)
+{
+ try
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: m_reallocator()");
+ #endif
+
+ // Calling realloc with a NULL should force same operations as a malloc
+
+ if (!reportedAddress)
+ {
+ return m_allocator(sourceFile, sourceLine, sourceFunc, reallocationType, reportedSize);
+ }
+
+ // Increase our allocation count
+
+ currentAllocationCount++;
+
+ // If you hit this assert, you requested a breakpoint on a specific allocation count
+ m_assert(currentAllocationCount != breakOnAllocationCount);
+
+ // Log the request
+
+ if (alwaysLogAll) log("[~] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[reallocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc));
+
+ // Locate the existing allocation unit
+
+ sAllocUnit *au = findAllocUnit(reportedAddress);
+
+ // If you hit this assert, you tried to reallocate RAM that wasn't allocated by this memory manager.
+ m_assert(au != NULL);
+ if (au == NULL) throw "Request to reallocate RAM that was never allocated";
+
+ // If you hit this assert, then the allocation unit that is about to be reallocated is damaged. But you probably
+ // already know that from a previous assert you should have seen in validateAllocUnit() :)
+ m_assert(m_validateAllocUnit(au));
+
+ // If you hit this assert, then this reallocation was made from a source that isn't setup to use this memory
+ // tracking software, use the stack frame to locate the source and include our H file.
+ m_assert(reallocationType != m_alloc_unknown);
+
+ // If you hit this assert, you were trying to reallocate RAM that was not allocated in a way that is compatible with
+ // realloc. In other words, you have a allocation/reallocation mismatch.
+ m_assert(au->allocationType == m_alloc_malloc ||
+ au->allocationType == m_alloc_calloc ||
+ au->allocationType == m_alloc_realloc);
+
+ // If you hit this assert, then the "break on realloc" flag for this allocation unit is set (and will continue to be
+ // set until you specifically shut it off. Interrogate the 'au' variable to determine information about this
+ // allocation unit.
+ m_assert(au->breakOnRealloc == false);
+
+ // Keep track of the original size
+
+ unsigned int originalReportedSize = static_cast<unsigned int>(au->reportedSize);
+
+ if (alwaysLogAll) log("[~] ----> from 0x%08X(%08d)", originalReportedSize, originalReportedSize);
+
+ // Do the reallocation
+
+ void *oldReportedAddress = reportedAddress;
+ size_t newActualSize = calculateActualSize(reportedSize);
+ void *newActualAddress = NULL;
+ #ifdef RANDOM_FAILURE
+ double a = rand();
+ double b = RAND_MAX / 100.0 * RANDOM_FAILURE;
+ if (a > b)
+ {
+ newActualAddress = realloc(au->actualAddress, newActualSize);
+ }
+ else
+ {
+ log("[F] Random faiure");
+ }
+ #else
+ newActualAddress = realloc(au->actualAddress, newActualSize);
+ #endif
+
+ // We don't want to assert with random failures, because we want the application to deal with them.
+
+ #ifndef RANDOM_FAILURE
+ // If you hit this assert, then the requested allocation simply failed (you're out of memory) Interrogate the
+ // variable 'au' to see the original allocation. You can also query 'newActualSize' to see the amount of memory
+ // trying to be allocated. Finally, you can query 'reportedSize' to see how much memory was requested by the caller.
+ m_assert(newActualAddress);
+ #endif
+
+ if (!newActualAddress) throw "Request for reallocation failed. Out of memory.";
+
+ // Remove this allocation from our stats (we'll add the new reallocation again later)
+
+ stats.totalReportedMemory -= static_cast<unsigned int>(au->reportedSize);
+ stats.totalActualMemory -= static_cast<unsigned int>(au->actualSize);
+
+ // Update the allocation with the new information
+
+ au->actualSize = newActualSize;
+ au->actualAddress = newActualAddress;
+ au->reportedSize = calculateReportedSize(newActualSize);
+ au->reportedAddress = calculateReportedAddress(newActualAddress);
+ au->allocationType = reallocationType;
+ au->sourceLine = sourceLine;
+ au->allocationNumber = currentAllocationCount;
+ if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1);
+ else strcpy (au->sourceFile, "??");
+ if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1);
+ else strcpy (au->sourceFunc, "??");
+
+ // The reallocation may cause the address to change, so we should relocate our allocation unit within the hash table
+
+ unsigned int hashIndex = static_cast<unsigned int>(-1);
+ if (oldReportedAddress != au->reportedAddress)
+ {
+ // Remove this allocation unit from the hash table
+
+ {
+ unsigned int hashIndex = (reinterpret_cast<unsigned int>(oldReportedAddress) >> 4) & (hashSize - 1);
+ if (hashTable[hashIndex] == au)
+ {
+ hashTable[hashIndex] = hashTable[hashIndex]->next;
+ }
+ else
+ {
+ if (au->prev) au->prev->next = au->next;
+ if (au->next) au->next->prev = au->prev;
+ }
+ }
+
+ // Re-insert it back into the hash table
+
+ hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+ if (hashTable[hashIndex]) hashTable[hashIndex]->prev = au;
+ au->next = hashTable[hashIndex];
+ au->prev = NULL;
+ hashTable[hashIndex] = au;
+ }
+
+ // Account for the new allocatin unit in our stats
+
+ stats.totalReportedMemory += static_cast<unsigned int>(au->reportedSize);
+ stats.totalActualMemory += static_cast<unsigned int>(au->actualSize);
+ if (stats.totalReportedMemory > stats.peakReportedMemory) stats.peakReportedMemory = stats.totalReportedMemory;
+ if (stats.totalActualMemory > stats.peakActualMemory) stats.peakActualMemory = stats.totalActualMemory;
+ int deltaReportedSize = static_cast<int>(reportedSize - originalReportedSize);
+ if (deltaReportedSize > 0)
+ {
+ stats.accumulatedReportedMemory += deltaReportedSize;
+ stats.accumulatedActualMemory += deltaReportedSize;
+ }
+
+ // Prepare the allocation unit for use (wipe it with recognizable garbage)
+
+ wipeWithPattern(au, unusedPattern, originalReportedSize);
+
+ // If you hit this assert, then something went wrong, because the allocation unit was properly validated PRIOR to
+ // the reallocation. This should not happen.
+ m_assert(m_validateAllocUnit(au));
+
+ // Validate every single allocated unit in memory
+
+ if (alwaysValidateAll) m_validateAllAllocUnits();
+
+ // Log the result
+
+ if (alwaysLogAll) log("[~] ----> addr 0x%08X", reinterpret_cast<unsigned int>(au->reportedAddress));
+
+ // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+ // source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+ resetGlobals();
+
+ // Return the (reported) address of the new allocation unit
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : m_reallocator()");
+ #endif
+
+ return au->reportedAddress;
+ }
+ catch(const char *err)
+ {
+ // Deal with the errors
+
+ log("[!] %s", err);
+ resetGlobals();
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : m_reallocator()");
+ #endif
+
+ return NULL;
+ }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Deallocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_deallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int deallocationType, const void *reportedAddress)
+{
+ try
+ {
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] ENTER: m_deallocator()");
+ #endif
+
+ // Log the request
+
+ if (alwaysLogAll) log("[-] ----- %8s of addr 0x%08X by %s", allocationTypes[deallocationType], reinterpret_cast<unsigned int>(const_cast<void *>(reportedAddress)), ownerString(sourceFile, sourceLine, sourceFunc));
+
+ // We should only ever get here with a null pointer if they try to do so with a call to free() (delete[] and delete will
+ // both bail before they get here.) So, since ANSI allows free(NULL), we'll not bother trying to actually free the allocated
+ // memory or track it any further.
+
+ if (reportedAddress)
+ {
+ // Go get the allocation unit
+
+ sAllocUnit *au = findAllocUnit(reportedAddress);
+
+ // If you hit this assert, you tried to deallocate RAM that wasn't allocated by this memory manager.
+ m_assert(au != NULL);
+ if (au == NULL) throw "Request to deallocate RAM that was never allocated";
+
+ // If you hit this assert, then the allocation unit that is about to be deallocated is damaged. But you probably
+ // already know that from a previous assert you should have seen in validateAllocUnit() :)
+ m_assert(m_validateAllocUnit(au));
+
+ // If you hit this assert, then this deallocation was made from a source that isn't setup to use this memory
+ // tracking software, use the stack frame to locate the source and include our H file.
+ m_assert(deallocationType != m_alloc_unknown);
+
+ // If you hit this assert, you were trying to deallocate RAM that was not allocated in a way that is compatible with
+ // the deallocation method requested. In other words, you have a allocation/deallocation mismatch.
+ m_assert((deallocationType == m_alloc_delete && au->allocationType == m_alloc_new ) ||
+ (deallocationType == m_alloc_delete_array && au->allocationType == m_alloc_new_array) ||
+ (deallocationType == m_alloc_free && au->allocationType == m_alloc_malloc ) ||
+ (deallocationType == m_alloc_free && au->allocationType == m_alloc_calloc ) ||
+ (deallocationType == m_alloc_free && au->allocationType == m_alloc_realloc ) ||
+ (deallocationType == m_alloc_unknown ) );
+
+ // If you hit this assert, then the "break on dealloc" flag for this allocation unit is set. Interrogate the 'au'
+ // variable to determine information about this allocation unit.
+ m_assert(au->breakOnDealloc == false);
+
+ // Wipe the deallocated RAM with a new pattern. This doen't actually do us much good in debug mode under WIN32,
+ // because Microsoft's memory debugging & tracking utilities will wipe it right after we do. Oh well.
+
+ wipeWithPattern(au, releasedPattern);
+
+ // Do the deallocation
+
+ free(au->actualAddress);
+
+ // Remove this allocation unit from the hash table
+
+ unsigned int hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+ if (hashTable[hashIndex] == au)
+ {
+ hashTable[hashIndex] = au->next;
+ }
+ else
+ {
+ if (au->prev) au->prev->next = au->next;
+ if (au->next) au->next->prev = au->prev;
+ }
+
+ // Remove this allocation from our stats
+
+ stats.totalReportedMemory -= static_cast<unsigned int>(au->reportedSize);
+ stats.totalActualMemory -= static_cast<unsigned int>(au->actualSize);
+ stats.totalAllocUnitCount--;
+
+ // Add this allocation unit to the front of our reservoir of unused allocation units
+
+ memset(au, 0, sizeof(sAllocUnit));
+ au->next = reservoir;
+ reservoir = au;
+ }
+
+ // Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+ // source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+ resetGlobals();
+
+ // Validate every single allocated unit in memory
+
+ if (alwaysValidateAll) m_validateAllAllocUnits();
+
+ // If we're in the midst of static deinitialization time, track any pending memory leaks
+
+ if (staticDeinitTime) dumpLeakReport();
+ }
+ catch(const char *err)
+ {
+ // Deal with errors
+
+ log("[!] %s", err);
+ resetGlobals();
+ }
+
+ #ifdef TEST_MEMORY_MANAGER
+ log("[D] EXIT : m_deallocator()");
+ #endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- The following utilitarian allow you to become proactive in tracking your own memory, or help you narrow in on those tough
+// bugs.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool m_validateAddress(const void *reportedAddress)
+{
+ // Just see if the address exists in our allocation routines
+
+ return findAllocUnit(reportedAddress) != NULL;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool m_validateAllocUnit(const sAllocUnit *allocUnit)
+{
+ // Make sure the padding is untouched
+
+ long *pre = reinterpret_cast<long *>(allocUnit->actualAddress);
+ long *post = reinterpret_cast<long *>((char *)allocUnit->actualAddress + allocUnit->actualSize - paddingSize * sizeof(long));
+ bool errorFlag = false;
+ for (unsigned int i = 0; i < paddingSize; i++, pre++, post++)
+ {
+ if (*pre != (long) prefixPattern)
+ {
+ log("[!] A memory allocation unit was corrupt because of an underrun:");
+ m_dumpAllocUnit(allocUnit, " ");
+ errorFlag = true;
+ }
+
+ // If you hit this assert, then you should know that this allocation unit has been damaged. Something (possibly the
+ // owner?) has underrun the allocation unit (modified a few bytes prior to the start). You can interrogate the
+ // variable 'allocUnit' to see statistics and information about this damaged allocation unit.
+ m_assert(*pre == static_cast<long>(prefixPattern));
+
+ if (*post != static_cast<long>(postfixPattern))
+ {
+ log("[!] A memory allocation unit was corrupt because of an overrun:");
+ m_dumpAllocUnit(allocUnit, " ");
+ errorFlag = true;
+ }
+
+ // If you hit this assert, then you should know that this allocation unit has been damaged. Something (possibly the
+ // owner?) has overrun the allocation unit (modified a few bytes after the end). You can interrogate the variable
+ // 'allocUnit' to see statistics and information about this damaged allocation unit.
+ m_assert(*post == static_cast<long>(postfixPattern));
+ }
+
+ // Return the error status (we invert it, because a return of 'false' means error)
+
+ return !errorFlag;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool m_validateAllAllocUnits()
+{
+ // Just go through each allocation unit in the hash table and count the ones that have errors
+
+ unsigned int errors = 0;
+ unsigned int allocCount = 0;
+ for (unsigned int i = 0; i < hashSize; i++)
+ {
+ sAllocUnit *ptr = hashTable[i];
+ while(ptr)
+ {
+ allocCount++;
+ if (!m_validateAllocUnit(ptr)) errors++;
+ ptr = ptr->next;
+ }
+ }
+
+ // Test for hash-table correctness
+
+ if (allocCount != stats.totalAllocUnitCount)
+ {
+ log("[!] Memory tracking hash table corrupt!");
+ errors++;
+ }
+
+ // If you hit this assert, then the internal memory (hash table) used by this memory tracking software is damaged! The
+ // best way to track this down is to use the alwaysLogAll flag in conjunction with STRESS_TEST macro to narrow in on the
+ // offending code. After running the application with these settings (and hitting this assert again), interrogate the
+ // memory.log file to find the previous successful operation. The corruption will have occurred between that point and this
+ // assertion.
+ m_assert(allocCount == stats.totalAllocUnitCount);
+
+ // If you hit this assert, then you've probably already been notified that there was a problem with a allocation unit in a
+ // prior call to validateAllocUnit(), but this assert is here just to make sure you know about it. :)
+ m_assert(errors == 0);
+
+ // Log any errors
+
+ if (errors) log("[!] While validting all allocation units, %d allocation unit(s) were found to have problems", errors);
+
+ // Return the error status
+
+ return errors != 0;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Unused RAM calculation routines. Use these to determine how much of your RAM is unused (in bytes)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int m_calcUnused(const sAllocUnit *allocUnit)
+{
+ const unsigned long *ptr = reinterpret_cast<const unsigned long *>(allocUnit->reportedAddress);
+ unsigned int count = 0;
+
+ for (unsigned int i = 0; i < allocUnit->reportedSize; i += sizeof(long), ptr++)
+ {
+ if (*ptr == unusedPattern) count += sizeof(long);
+ }
+
+ return count;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int m_calcAllUnused()
+{
+ // Just go through each allocation unit in the hash table and count the unused RAM
+
+ unsigned int total = 0;
+ for (unsigned int i = 0; i < hashSize; i++)
+ {
+ sAllocUnit *ptr = hashTable[i];
+ while(ptr)
+ {
+ total += m_calcUnused(ptr);
+ ptr = ptr->next;
+ }
+ }
+
+ return total;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- The following functions are for logging and statistics reporting.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_dumpAllocUnit(const sAllocUnit *allocUnit, const char *prefix)
+{
+ log("[I] %sAddress (reported): %010p", prefix, allocUnit->reportedAddress);
+ log("[I] %sAddress (actual) : %010p", prefix, allocUnit->actualAddress);
+ log("[I] %sSize (reported) : 0x%08X (%s)", prefix, static_cast<unsigned int>(allocUnit->reportedSize), memorySizeString(static_cast<unsigned int>(allocUnit->reportedSize)));
+ log("[I] %sSize (actual) : 0x%08X (%s)", prefix, static_cast<unsigned int>(allocUnit->actualSize), memorySizeString(static_cast<unsigned int>(allocUnit->actualSize)));
+ log("[I] %sOwner : %s(%d)::%s", prefix, allocUnit->sourceFile, allocUnit->sourceLine, allocUnit->sourceFunc);
+ log("[I] %sAllocation type : %s", prefix, allocationTypes[allocUnit->allocationType]);
+ log("[I] %sAllocation number : %d", prefix, allocUnit->allocationNumber);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_dumpMemoryReport(const char *filename, const bool overwrite)
+{
+ // Open the report file
+
+ FILE *fp = NULL;
+
+ if (overwrite) fp = fopen(filename, "w+b");
+ else fp = fopen(filename, "ab");
+
+ // If you hit this assert, then the memory report generator is unable to log information to a file (can't open the file for
+ // some reason.)
+ m_assert(fp);
+ if (!fp) return;
+
+ // Header
+
+ static char timeString[25];
+ memset(timeString, 0, sizeof(timeString));
+ time_t t = time(NULL);
+ struct tm *tme = localtime(&t);
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| Memory report for: %02d/%02d/%04d %02d:%02d:%02d |\r\n", tme->tm_mon + 1, tme->tm_mday, tme->tm_year + 1900, tme->tm_hour, tme->tm_min, tme->tm_sec);
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "\r\n");
+ fprintf(fp, "\r\n");
+
+ // Report summary
+
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| T O T A L S |\r\n");
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, " Allocation unit count: %10s\r\n", insertCommas(stats.totalAllocUnitCount));
+ fprintf(fp, " Reported to application: %s\r\n", memorySizeString(stats.totalReportedMemory));
+ fprintf(fp, " Actual total memory in use: %s\r\n", memorySizeString(stats.totalActualMemory));
+ fprintf(fp, " Memory tracking overhead: %s\r\n", memorySizeString(stats.totalActualMemory - stats.totalReportedMemory));
+ fprintf(fp, "\r\n");
+
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| P E A K S |\r\n");
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, " Allocation unit count: %10s\r\n", insertCommas(stats.peakAllocUnitCount));
+ fprintf(fp, " Reported to application: %s\r\n", memorySizeString(stats.peakReportedMemory));
+ fprintf(fp, " Actual: %s\r\n", memorySizeString(stats.peakActualMemory));
+ fprintf(fp, " Memory tracking overhead: %s\r\n", memorySizeString(stats.peakActualMemory - stats.peakReportedMemory));
+ fprintf(fp, "\r\n");
+
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| A C C U M U L A T E D |\r\n");
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, " Allocation unit count: %s\r\n", memorySizeString(stats.accumulatedAllocUnitCount));
+ fprintf(fp, " Reported to application: %s\r\n", memorySizeString(stats.accumulatedReportedMemory));
+ fprintf(fp, " Actual: %s\r\n", memorySizeString(stats.accumulatedActualMemory));
+ fprintf(fp, "\r\n");
+
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, "| U N U S E D |\r\n");
+ fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+ fprintf(fp, " Memory allocated but not in use: %s\r\n", memorySizeString(m_calcAllUnused()));
+ fprintf(fp, "\r\n");
+
+ dumpAllocations(fp);
+
+ fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+sMStats m_getMemoryStatistics()
+{
+ return stats;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// mmgr.cpp - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _
+// | |
+// _ __ ___ _ __ ___ __ _ _ __ | |__
+// | '_ ` _ \| '_ ` _ \ / _` | '__| | '_ \
+// | | | | | | | | | | | (_| | | _ | | | |
+// |_| |_| |_|_| |_| |_|\__, |_| (_)|_| |_|
+// __/ |
+// |___/
+//
+// Memory manager & tracking software
+//
+// Best viewed with 8-character tabs and (at least) 132 columns
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 12/22/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifndef _H_MMGR
+#define _H_MMGR
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// For systems that don't have the __FUNCTION__ variable, we can just define it here
+// ---------------------------------------------------------------------------------------------------------------------------------
+#ifndef __FUNCTION__
+#define __FUNCTION__ "??"
+#endif
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+typedef struct tag_au
+{
+ size_t actualSize;
+ size_t reportedSize;
+ void *actualAddress;
+ void *reportedAddress;
+ char sourceFile[40];
+ char sourceFunc[40];
+ unsigned int sourceLine;
+ unsigned int allocationType;
+ bool breakOnDealloc;
+ bool breakOnRealloc;
+ unsigned int allocationNumber;
+ struct tag_au *next;
+ struct tag_au *prev;
+} sAllocUnit;
+
+typedef struct
+{
+ unsigned int totalReportedMemory;
+ unsigned int totalActualMemory;
+ unsigned int peakReportedMemory;
+ unsigned int peakActualMemory;
+ unsigned int accumulatedReportedMemory;
+ unsigned int accumulatedActualMemory;
+ unsigned int accumulatedAllocUnitCount;
+ unsigned int totalAllocUnitCount;
+ unsigned int peakAllocUnitCount;
+} sMStats;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// External constants
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+extern const unsigned int m_alloc_unknown;
+extern const unsigned int m_alloc_new;
+extern const unsigned int m_alloc_new_array;
+extern const unsigned int m_alloc_malloc;
+extern const unsigned int m_alloc_calloc;
+extern const unsigned int m_alloc_realloc;
+extern const unsigned int m_alloc_delete;
+extern const unsigned int m_alloc_delete_array;
+extern const unsigned int m_alloc_free;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Used by the macros
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_setOwner(const char *file, const unsigned int line, const char *func);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Allocation breakpoints
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool &m_breakOnRealloc(void *reportedAddress);
+bool &m_breakOnDealloc(void *reportedAddress);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The meat of the memory tracking software
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *m_allocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+ const unsigned int allocationType, const size_t reportedSize);
+void *m_reallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+ const unsigned int reallocationType, const size_t reportedSize, void *reportedAddress);
+void m_deallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+ const unsigned int deallocationType, const void *reportedAddress);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Utilitarian functions
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool m_validateAddress(const void *reportedAddress);
+bool m_validateAllocUnit(const sAllocUnit *allocUnit);
+bool m_validateAllAllocUnits();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Unused RAM calculations
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int m_calcUnused(const sAllocUnit *allocUnit);
+unsigned int m_calcAllUnused();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Logging and reporting
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void m_dumpAllocUnit(const sAllocUnit *allocUnit, const char *prefix = "");
+void m_dumpMemoryReport(const char *filename = "memreport.log", const bool overwrite = true);
+sMStats m_getMemoryStatistics();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Variations of global operators new & delete
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void *operator new(size_t reportedSize);
+void *operator new[](size_t reportedSize);
+void *operator new(size_t reportedSize, const char *sourceFile, int sourceLine);
+void *operator new[](size_t reportedSize, const char *sourceFile, int sourceLine);
+void operator delete(void *reportedAddress);
+void operator delete[](void *reportedAddress);
+
+#endif // _H_MMGR
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Macros -- "Kids, please don't try this at home. We're trained professionals here." :)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#include "nommgr.h"
+#define new (m_setOwner (__FILE__,__LINE__,__FUNCTION__),false) ? NULL : new
+#define delete (m_setOwner (__FILE__,__LINE__,__FUNCTION__),false) ? m_setOwner("",0,"") : delete
+#define malloc(sz) m_allocator (__FILE__,__LINE__,__FUNCTION__,m_alloc_malloc,sz)
+#define calloc(sz) m_allocator (__FILE__,__LINE__,__FUNCTION__,m_alloc_calloc,sz)
+#define realloc(ptr,sz) m_reallocator(__FILE__,__LINE__,__FUNCTION__,m_alloc_realloc,sz,ptr)
+#define free(ptr) m_deallocator(__FILE__,__LINE__,__FUNCTION__,m_alloc_free,ptr)
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// mmgr.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
--- /dev/null
+// ---------------------------------------------------------------------------------------------------------------------------------
+// _
+// | |
+// _ __ ___ _ __ ___ _ __ ___ __ _ _ __ | |__
+// | '_ \ / _ \| '_ ` _ \| '_ ` _ \ / _` | '__| | '_ \
+// | | | | (_) | | | | | | | | | | | (_| | | _ | | | |
+// |_| |_|\___/|_| |_| |_|_| |_| |_|\__, |_| (_)|_| |_|
+// __/ |
+// |___/
+//
+// Memory manager & tracking software
+//
+// Best viewed with 8-character tabs and (at least) 132 columns
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+//
+// Restrictions & freedoms pertaining to usage and redistribution of this software:
+//
+// * This software is 100% free
+// * If you use this software (in part or in whole) you must credit the author.
+// * This software may not be re-distributed (in part or in whole) in a modified
+// form without clear documentation on how to obtain a copy of the original work.
+// * You may not use this software to directly or indirectly cause harm to others.
+// * This software is provided as-is and without warrantee. Use at your own risk.
+//
+// For more information, visit HTTP://www.FluidStudios.com
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 12/22/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifdef new
+#undef new
+#endif
+
+#ifdef delete
+#undef delete
+#endif
+
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef calloc
+#undef calloc
+#endif
+
+#ifdef realloc
+#undef realloc
+#endif
+
+#ifdef free
+#undef free
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// nommgr.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
--- /dev/null
+/*
+ * Copyright (c) 2002 Lane Roathe. All rights reserved.
+ * Developed in cooperation with Freeverse, Inc.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * Portions Copyright (c) 1999-2002 Apple Computer, Inc. All Rights
+ * Reserved. This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.1 (the "License"). You may not use this file
+ * except in compliance with the License. Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ *
+ * Modified: $Date: 2002/04/27 21:42:01 $
+ * Revision: $Id: nsp_network.c,v 1.1 2002/04/27 21:42:01 lane Exp $
+ */
+
+/* NOTES:
+
+ - This example is designed so that all networking code is in this one file. The purpose is to make
+ it easier for a programmer to study the basic use of OpenPlay's NetSprocket API and not to
+ demonstrate good programming style or OOP practices.
+
+ - This file is not game independent (hey, that's what OpenPlay is about!), it simply helped me keep
+ the example use of NetSprocket's more managable ... I hope :)
+
+ - I wanted the host (ie, server) to also be a player, and found it was pretty easy to do; I simply
+ made sure that I tracked whether I was a server or client (see the _server variable in main.h) and
+ then when sending all players a message I had to modify the "to" portion of the header and
+ resend it to the host. This means the host is sending itself messages, which works great.
+
+*/
+
+/* ----------------------------------------------------------- Includes */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "main.h"
+
+#include "network.h"
+
+/* ----------------------------------------------------------- Macro definitions */
+
+enum
+{
+ kMessageType_Question = 256,
+ kMessageType_Answer,
+
+ kMessageType_Information
+};
+
+#define kPlayerType 1234 /* just defines a way to allow/reject players of different types */
+
+
+/* ----------------------------------------------------------- Type definitions */
+
+/* Questions are sent out in message packets from server to players */
+
+/* NOTE Message string is ZERO terminated! */
+/* This allows us to strcpy, strcmp, etc. on raw packet data */
+/* Meaning packet size = sizeof(packet_t) + strlen(string) */
+
+typedef struct
+{
+ NSpMessageHeader header;
+
+ char str[1]; /* message (question, info, etc) string */
+
+}MessagePacket_t, *MessagePacketPtr;
+
+/* Answers are sent from the players to the server in this packet */
+
+typedef struct
+{
+ NSpMessageHeader header;
+
+ char answer; /* finally, the answer */
+
+}AnswerPacket_t, *AnswerPacketPtr;
+
+/* ----------------------------------------------------------- Local Variables */
+
+/* name of this version of the app*/
+char *GameNameStr = "OpenPlay NSp API Example 1";
+
+/* Local vars used to handle our interaction with OpenPlay's NetSprockets API */
+
+static NSpGameReference _gameReference = NULL; /* general game info */
+static NSpProtocolListReference _protocolListRef = NULL; /* list of protocols we've started up */
+
+static NMBoolean _approved; /* after requesting to join a new game, this tracks whether or not we were approved */
+static NMBoolean _response; /* true if we get a response following a request to join a new game (else we time out */
+
+/*--------------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------------*/
+#if __MWERKS__
+ #pragma mark -
+ #pragma mark È Local Routines
+ #pragma mark -
+#endif
+
+
+/*--------------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------------*/
+#if __MWERKS__
+ #pragma mark -
+ #pragma mark È Global Routines
+ #pragma mark -
+#endif
+
+unsigned char *GameC2PStr
+(
+ char *s, /* source C string */
+ unsigned char *d /* destination buffer for Pascal string */
+)
+{
+ int c = 0;
+
+ if( s && d ) /* make sure we got got inputs */
+ {
+ while( *s )
+ d[++c] = (unsigned char)*s++; /* no blockmove, copy & get length in one shot */
+ }
+ *d = (unsigned char)c;
+
+ return( d );
+}
+
+char *GameP2CStr
+(
+ unsigned char *s, /* source Pascal string */
+ char *d /* buffer to hold converted C string */
+)
+{
+ if( s && d )
+ {
+ memcpy( d, s+1, *s ); /* pretty simple */
+ d[*s] = 0;
+ }
+ return( d );
+}
+
+/* ================================================================================
+ Handle all of the network messages that are sent to this application
+
+ EXIT: 0 == no error, else error code
+*/
+
+void NetworkHandleMessage( void )
+{
+ NSpMessageHeader *mhp;
+ char str[256]; /* buffer for converted PStrings */
+
+ /* Ask NetSprocket to give us a message if any are waiting */
+
+ mhp = NSpMessage_Get( _gameReference );
+ if( mhp )
+ {
+ /* Print out the type of message received */
+
+ switch(mhp -> what)
+ {
+
+/* --- Handle NetSprocket's generic messages */
+
+ case kNSpJoinApproved:
+ printf( "Approved!\n\n", str );
+ fflush(stdout);
+ _response = true;
+ _approved = true; /* tell our waiting loop that we were approved */
+#if __USE_SIOUX__
+ {
+ NMErr err;
+
+ err = NSpGame_GetInfo( _gameReference, &gameInfo );
+ if( !err )
+ SIOUXSetTitle( gameInfo.name );
+ }
+#endif
+ break;
+
+ case kNSpJoinDenied:
+ GameP2CStr( ((NSpJoinDeniedMessage *)mhp)->reason, str );
+ printf( "Denied!\n Reason: %s\n\n", str );
+ fflush(stdout);
+ //GameOver();
+
+ _response = true;
+ _approved = false; /* tell our waiting loop we were denied */
+ break;
+
+ case kNSpError:
+ printf( "*** ERROR *** (reported value: %d)\n\n", ((NSpErrorMessage *)mhp)->error );
+ fflush(stdout);
+
+ _response = true;
+ _approved = false;
+ break;
+
+ case kNSpGameTerminated:
+ printf( "--- Host Terminated Game ---\n\n" );
+ fflush(stdout);
+ //GameOver();
+
+ _response = true;
+ _approved = false;
+ break;
+
+ case kNSpPlayerJoined:
+ {
+ NSpGameInfo gameInfo;
+ char gamename[256];
+ NMErr err;
+
+ err = NSpGame_GetInfo( _gameReference, &gameInfo );
+ if( !err )
+ GameP2CStr( gameInfo.name, gamename );
+ else
+ strcpy( gamename, "ERRROR" );
+
+ GameP2CStr( ((NSpPlayerJoinedMessage *)mhp)->playerInfo.name, str );
+ printf( "===> Player %s joined game '%s', %d players now!\n\n",
+ str, gamename, ((NSpPlayerJoinedMessage *)mhp)->playerCount );
+ fflush(stdout);
+
+ /* Lets go ahead and re-send the current question, as the new guy deserves a shot at it too */
+ /*if( GameIsHost() )
+ {
+ //QuestionPtr theQuestion = GameGetCurrentQuestion();
+ //if (theQuestion)
+ // NetworkSendQuestion(theQuestion->question);
+ }*/
+ }
+ break;
+
+ case kNSpPlayerLeft:
+ GameP2CStr( ((NSpPlayerLeftMessage *)mhp)->playerName, str );
+ printf( "===> Player, %s, Left game, leaving %d players!\n\n",
+ str, ((NSpPlayerLeftMessage *)mhp)->playerCount );
+ fflush(stdout);
+ break;
+
+ case kNSpHostChanged:
+ printf( "===> ??? Host changed to player ID %d\n\n",
+ ((NSpHostChangedMessage *)mhp)->newHost );
+ fflush(stdout);
+ break;
+
+ case kNSpGroupCreated:
+ printf( "===> Player #%d created a new Group, ID %d\n\n",
+ ((NSpCreateGroupMessage *)mhp)->requestingPlayer, ((NSpCreateGroupMessage *)mhp)->groupID );
+ fflush(stdout);
+ break;
+
+ case kNSpGroupDeleted:
+ printf( "===> Player #%d deleted group #%d\n\n",
+ ((NSpDeleteGroupMessage *)mhp)->requestingPlayer, ((NSpDeleteGroupMessage *)mhp)->groupID );
+ fflush(stdout);
+ break;
+
+ case kNSpPlayerAddedToGroup:
+ printf( "===> Player %d was added to group %d\n\n",
+ ((NSpAddPlayerToGroupMessage *)mhp)->player, ((NSpAddPlayerToGroupMessage *)mhp)->group );
+ fflush(stdout);
+ break;
+
+ case kNSpPlayerRemovedFromGroup:
+ printf( "===> Player %d was removed from group %d\n\n",
+ ((NSpRemovePlayerFromGroupMessage *)mhp)->player, ((NSpRemovePlayerFromGroupMessage *)mhp)->group );
+ fflush(stdout);
+ break;
+
+ case kNSpPlayerTypeChanged:
+ printf( "===> Player %d changed to a new type, %d\n\n",
+ ((NSpPlayerTypeChangedMessage *)mhp)->player, ((NSpPlayerTypeChangedMessage *)mhp)->newType );
+ break;
+
+
+/* --- Handle our game specific messages */
+
+
+ /* Got a message, see if it is correct or not and let everyone know the results */
+
+ case kMessageType_Answer:
+ {
+ NSpPlayerInfoPtr pip;
+ char cname[kNSpStr32Len];
+ NMErr err;
+
+ err = NSpPlayer_GetInfo( _gameReference, mhp->from, &pip );
+ if( !err )
+ {
+ GameP2CStr( pip->name, cname );
+
+ NSpPlayer_ReleaseInfo( _gameReference, pip );
+ }
+ else
+ strcpy( cname, "UNKOWN -- error!" );
+
+ //sprintf( str, "Player #%d, %s, answered with '%c', which is %s", mhp->from, cname, ((AnswerPacketPtr)mhp)->answer,
+ //GameCheckAnswer( ((AnswerPacketPtr)mhp)->answer ) ? "Correct!" : "WRONG!" );
+
+ NetworkSendInformation( str );
+ }
+ break;
+
+ /* allow game to do any special processing needed when a question arrives */
+
+ case kMessageType_Question:
+ //GameDisplayQuestion( ((MessagePacketPtr)mhp)->str );
+ break;
+
+ /* pretty simple, just display the info message */
+
+ case kMessageType_Information:
+ printf( "%s\n\n", ((MessagePacketPtr)mhp)->str );
+ fflush(stdout);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Once done with it, release the message */
+
+ NSpMessage_Release( _gameReference, mhp );
+ }
+}
+
+/* ================================================================================
+ Return the # of players in the current game
+
+ EXIT: none
+*/
+
+NMUInt32 NetworkGetPlayerCount( void )
+{
+ NSpGameInfo gameInfo;
+ NMErr err;
+
+ err = NSpGame_GetInfo( _gameReference, &gameInfo ); /* player count is in the game info record */
+ if( !err )
+ {
+ return( gameInfo.currentPlayers );
+ }
+
+ return( 0 );
+}
+
+/* ================================================================================
+ Send an answer to the server
+
+ EXIT: none
+*/
+
+NMErr NetworkSendAnswer
+(
+ char answer /* the answer to send (just a char!) */
+)
+{
+ AnswerPacket_t answerPacket;
+ NMErr err;
+
+ /* init the NetSprocket portion of the packet */
+
+ NSpClearMessageHeader( &answerPacket.header );
+
+ answerPacket.header.what = kMessageType_Answer;
+ answerPacket.header.to = kNSpHostOnly;
+ answerPacket.header.messageLen = sizeof(answerPacket);
+
+ /* fill in the data section */
+
+ answerPacket.answer = answer;
+
+ /* tell NetSprocket to send the message */
+
+ err = NSpMessage_Send( _gameReference, &answerPacket.header, kNSpSendFlag_Registered );
+ if( err )
+ {
+ printf( "*** ERROR *** Unable to send answer packet, error # %d\n\n", err );
+ fflush(stdout);
+ }
+
+ return( err );
+}
+
+/* ================================================================================
+ Send a message to all players
+
+ EXIT: none
+*/
+
+NMErr NetworkSendPlayerMessage
+(
+ const char *message, /* ptr to message string to send */
+ NMUInt32 messageType /* type of message (question, info, etc. */
+)
+{
+ MessagePacketPtr qpp;
+ unsigned long messageLen, size;
+ NMErr err;
+
+ /* sanity checks */
+
+ if( !message )
+ return( kNSpInvalidParameterErr );
+
+ /* get size of message string & total size of network packet */
+
+ messageLen = strlen( message );
+ size = sizeof(MessagePacket_t) + messageLen + 1; /* header + num_chars + terminator */
+
+ /* allocate the memory for the packet */
+
+ qpp = (MessagePacketPtr)malloc( size );
+ if( !qpp )
+ {
+ printf( " *** ERROR *** Unable to allocate message buffer!\n\n" );
+ fflush(stdout);
+ return( kNSpMemAllocationErr );
+ }
+
+ /* init the NetSprocket portion of the packet */
+
+ NSpClearMessageHeader( &qpp->header );
+
+ qpp->header.what = (NMSInt32)messageType;
+ qpp->header.to = kNSpAllPlayers;
+ qpp->header.messageLen = size;
+
+ /* fill in the data section */
+
+ strcpy( qpp->str, message );
+
+ /* tell NetSprocket to send the message */
+
+ err = NSpMessage_Send( _gameReference, &qpp->header, kNSpSendFlag_Registered );
+ if( !err )
+ {
+ qpp->header.to = kNSpHostOnly; /* allow host to play as well! */
+
+ err = NSpMessage_Send( _gameReference, &qpp->header, kNSpSendFlag_Registered );
+ }
+
+ if( err )
+ {
+ printf( "*** ERROR *** Unable to send message packet, error # %d\n\n", err );
+ fflush(stdout);
+ }
+
+ /* clean up after ourselves! */
+
+ free( qpp );
+
+ return( err );
+}
+
+/* ================================================================================
+ Send a question to all players
+
+ EXIT: none
+*/
+
+NMErr NetworkSendQuestion
+(
+ const char *question /* ptr to question string to send */
+)
+{
+ return( NetworkSendPlayerMessage( question, kMessageType_Question ) );
+}
+
+/* ================================================================================
+ Send information to all players
+
+ EXIT: none
+*/
+
+NMErr NetworkSendInformation
+(
+ const char *message /* ptr to information string to send */
+)
+{
+ return( NetworkSendPlayerMessage( message, kMessageType_Information ) );
+}
+
+#if __MWERKS__
+ #pragma mark -
+#endif
+
+/* ================================================================================
+ Initialize server networking
+
+ EXIT: 0 == no error, else error code
+*/
+
+NMErr NetworkStartServer
+(
+ NMUInt16 port, /* port clients will connect on */
+ NMUInt32 maxPlayers, /* max # of players to allow into game */
+ const unsigned char *gameName, /* name of game (displayed to clients on connect) */
+ const unsigned char *playerName /* name of player on server computer */
+)
+{
+ NSpProtocolReference protocolRef;
+ NMErr err;
+
+ /* Create a new protocol list to store our IP protocol reference in */
+
+ err = NSpProtocolList_New( NULL, &_protocolListRef );
+ if( !err )
+ {
+ /* Create a protocol reference for our IP connection, on our specified port w/default maxRTT and throughput */
+
+ protocolRef = NSpProtocol_CreateIP( port, 0, 0 );
+ if( protocolRef )
+ {
+ /* We got a good reference, append it to the list we created earlier */
+
+ err = NSpProtocolList_Append( _protocolListRef, protocolRef );
+ if( !err )
+ {
+ /* We got a protocol and it's in our reference list, now we can create the game
+ to host, using the parms sent in and defaulting rest of the "unused" hosting parms */
+
+ err = NSpGame_Host( &_gameReference, _protocolListRef, maxPlayers, gameName,
+ "\pPassword", playerName, kPlayerType, kNSpClientServer, 0 );
+ }
+ }
+ else
+ err = kNSpInvalidProtocolRefErr; /* assign somewhat meaningful error on failure to create protocol reference */
+ }
+
+ return( err );
+}
+
+
+/* ================================================================================
+ Shutdown the networking, release resources, etc.
+
+ EXIT: 0 == no error, else error code
+*/
+
+NMErr NetworkStartClient
+(
+ char *ipAddr, /* IP address (or domain name) to look for server (host) on */
+ char *port, /* Port to talk to server via */
+ const unsigned char *playerName /* name of player wanting to join */
+)
+{
+ NSpAddressReference addRef;
+ NMErr err;
+
+ /* Given our input strings, create an OpenPlay address reference for talking to server */
+
+ addRef = NSpCreateIPAddressReference( ipAddr, port );
+ if( addRef )
+ {
+ printf( "\nAttempting to join game..." );
+ fflush(stdout);
+
+ /* Now, look for a server on the IP/Port given and see if we can connect */
+
+ err = NSpGame_Join( &_gameReference, addRef, playerName, "\pPassword", kPlayerType, NULL, 0, 0 );
+ if( !err )
+ {
+ NMUInt32 startTime, currentTime;
+ time_t seconds;
+
+ printf( "connected!\n\nWaiting for approval to join game (press 'q' to quit)..." );
+ fflush(stdout);
+
+ time(&seconds);
+ startTime = seconds;
+
+ _response = _approved = false;
+
+ /* We connected, now we have to wait for the server to approve our join request */
+
+ while( !_response )
+ {
+ /* Check for a time out in connecting to server */
+ /* this is before the event handler so that we are not approved, but time out anyway (small chance, but...) */
+
+ time(&seconds);
+ currentTime = seconds;
+
+ if( (currentTime - startTime > 60) && (!_response) )
+ {
+ printf( "ERROR: Connection timed out!\n\n" );
+ fflush(stdout);
+
+ _response = true;
+ _approved = false;
+ }
+
+ /* Handle system messages and allow user to quit via 'q' */
+ /* This also gets and handles network messages, like accept/deny */
+
+ //GameHandleEvents();
+ }
+
+ /* if we were not approved, we must dispose of the game object here */
+
+ if( !_approved )
+ {
+ err = NSpGame_Dispose( _gameReference, kNSpGameFlag_ForceTerminateGame );
+ _gameReference = NULL;
+ }
+ else /* let the user know that they were accepted to the game */
+ {
+ NSpGameInfo gameInfo;
+ char str[256];
+
+ err = NSpGame_GetInfo( _gameReference, &gameInfo );
+ if( !err )
+ {
+ GameP2CStr( gameInfo.name, str );
+
+ printf( " Welcome to the game '%s', with %d players\n\n", str, (int)gameInfo.currentPlayers );
+ fflush(stdout);
+ }
+ }
+ }
+ }
+ else
+ err = kNMParameterErr;
+
+ return( err );
+}
+
+
+#if __MWERKS__
+ #pragma mark -
+#endif
+
+/* ================================================================================
+ Shutdown the networking, release resources, etc.
+
+ EXIT: 0 == no error, else error code
+*/
+
+NMErr NetworkShutdown( void )
+{
+ NMUInt32 refCount;
+ NMErr err = kNMNoError;
+
+ /* if we have a game object (we should!) dispose if it now */
+
+ if( _gameReference )
+ err = NSpGame_Dispose( _gameReference, kNSpGameFlag_ForceTerminateGame );
+
+ /* dispose of our protocol references & the list containing them */
+
+ if( _protocolListRef )
+ {
+ NSpProtocolReference pRef;
+
+ refCount = NSpProtocolList_GetCount( _protocolListRef ); /* get number of protocols */
+
+ while( refCount-- && !err )
+ {
+ pRef = NSpProtocolList_GetIndexedRef( _protocolListRef, refCount ); /* get currect reference */
+
+ err = NSpProtocolList_RemoveIndexed( _protocolListRef, refCount ); /* then remove it from the list */
+
+ /* now, we can dispose of the reference safely */
+ NSpProtocol_Dispose( pRef ); /* this should have an NMErr return, but has a void return... */
+ }
+
+ /* once all of the protocols are disposed, we can dispose of the containing reference list */
+ NSpProtocolList_Dispose( _protocolListRef );
+ }
+
+
+ /* Make sure we can't use old values */
+
+ _protocolListRef = NULL;
+ _gameReference = NULL;
+
+ return( err );
+}
+
+/* ================================================================================
+ Startup the networking system (NetSprockets in this case)
+
+ EXIT: 0 == no error, else error code
+*/
+
+NMErr NetworkStartup( void )
+{
+ NMErr err;
+
+ /* First, make sure that NetSprockets is available (we weak linked to OpenPlayStubLib) */
+
+ if( NULL == NSpInitialize ) /*|| NULL == ProtocolAcceptConnection )*/
+ return( errModuleNotFound );
+
+ /* Initialize NetSprockets, 0 == use defaults & NSe1 stands for "NetSprocket Example 1"
+ It is an identifier for games of our type on the network */
+
+ err = NSpInitialize( 0, 0, 0, 'NSe1', 0 );
+
+ return( err );
+}
--- /dev/null
+#include <stdlib.h>
+
+#include "binio.h"
+#include "private.h"
+#include "pack_private.h"
+
+extern void packf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfpackf(stdout, format, args);
+ va_end(args);
+}
+
+extern void spackf(void *buffer, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vspackf(buffer, format, args);
+ va_end(args);
+}
+
+extern void fpackf(FILE *file, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfpackf(file, format, args);
+ va_end(args);
+}
+
+extern void vspackf(void *buffer, const char *format, va_list args)
+{
+ struct BinIOFormatCursor cursor;
+ struct BinIOPackContext context;
+
+ BinIOInitFormatCursor(&cursor, format);
+
+ context.buffer = (unsigned char *)buffer;
+ context.args = args;
+
+ while (BinIONextChar(&context, &cursor, BinIOPack)) {}
+}
+
+extern void vfpackf(FILE *file, const char *format, va_list args)
+{
+ size_t n_bytes = BinIOFormatByteCount(format);
+ void* buffer = malloc(n_bytes);
+
+ vspackf(buffer, format, args);
+
+ fwrite(buffer, n_bytes, 1, file);
+ free(buffer);
+}
--- /dev/null
+#include "pack_private.h"
+
+void BinIOPack(void *context, int type, int byte_order, int count)
+{
+ struct BinIOPackContext *ctx = (struct BinIOPackContext*)context;
+ if (count == -1)
+ {
+ switch (type)
+ {
+ case BinIO_TYPE_IGNORE_BYTE:
+ {
+ ctx->buffer += 1;
+ }
+ break;
+ case BinIO_TYPE_BYTE:
+ {
+ uint8_t value = va_arg(ctx->args, int);
+ BinIOConvert1(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 1;
+ }
+ break;
+ case BinIO_TYPE_INT16:
+ {
+ uint16_t value = va_arg(ctx->args, int);
+ BinIOConvert2(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 2;
+ }
+ break;
+ case BinIO_TYPE_INT32:
+ {
+ int value = va_arg(ctx->args, int);
+ BinIOConvert4(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 4;
+ }
+ break;
+ case BinIO_TYPE_INT64:
+ {
+ uint64_t value = va_arg(ctx->args, uint64_t);
+ BinIOConvert8(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 8;
+ }
+ break;
+ case BinIO_TYPE_FLOAT32:
+ {
+ float32_t value = (float32_t)va_arg(ctx->args, double);
+ BinIOConvert4(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 4;
+ }
+ break;
+ case BinIO_TYPE_FLOAT64:
+ {
+ float64_t value = va_arg(ctx->args, float64_t);
+ BinIOConvert8(BinIO_HOST_BYTE_ORDER, byte_order, (const uint8_t *)&value, ctx->buffer, 1);
+ ctx->buffer += 8;
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (type)
+ {
+ case BinIO_TYPE_IGNORE_BYTE: ctx->buffer += 1 * count; break;
+ case BinIO_TYPE_BYTE: BinIOConvert1(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 1 * count; break;
+ case BinIO_TYPE_INT16: BinIOConvert2(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 2 * count; break;
+ case BinIO_TYPE_INT32: BinIOConvert4(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 4 * count; break;
+ case BinIO_TYPE_INT64: BinIOConvert8(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 8 * count; break;
+ case BinIO_TYPE_FLOAT32: BinIOConvert4(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 4 * count; break;
+ case BinIO_TYPE_FLOAT64: BinIOConvert8(BinIO_HOST_BYTE_ORDER, byte_order, va_arg(ctx->args, uint8_t *), ctx->buffer, count); ctx->buffer += 8 * count; break;
+ }
+ }
+}
--- /dev/null
+#ifndef pack_private_h
+#define pack_private_h
+
+#include "private.h"
+
+struct BinIOPackContext
+{
+ uint8_t *buffer;
+ va_list args;
+};
+
+extern void BinIOPack(void *context, int type, int byte_order, int count);
+
+#endif
--- /dev/null
+#include <string.h>
+
+#include "private.h"
+
+void BinIOConvert1(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count)
+{
+ if (BinIONormalizeByteOrder(from_byte_order) !=
+ BinIONormalizeByteOrder(to_byte_order))
+ {
+ unsigned int i;
+ for (i = 0; i < count; ++i)
+ {
+ BinIOSwap1(src, dst);
+ src += 1;
+ dst += 1;
+ }
+ }
+ else
+ {
+ memcpy(dst, src, 1 * count);
+ }
+}
+
+void BinIOConvert2(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count)
+{
+ if (BinIONormalizeByteOrder(from_byte_order) !=
+ BinIONormalizeByteOrder(to_byte_order))
+ {
+ unsigned int i;
+ for (i = 0; i < count; ++i)
+ {
+ BinIOSwap2(src, dst);
+ src += 2;
+ dst += 2;
+ }
+ }
+ else
+ {
+ memcpy(dst, src, 2 * count);
+ }
+}
+
+void BinIOConvert4(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count)
+{
+ if (BinIONormalizeByteOrder(from_byte_order) !=
+ BinIONormalizeByteOrder(to_byte_order))
+ {
+ unsigned int i;
+ for (i = 0; i < count; ++i)
+ {
+ BinIOSwap4(src, dst);
+ src += 4;
+ dst += 4;
+ }
+ }
+ else
+ {
+ memcpy(dst, src, 4 * count);
+ }
+}
+
+void BinIOConvert8(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count)
+{
+ if (BinIONormalizeByteOrder(from_byte_order) !=
+ BinIONormalizeByteOrder(to_byte_order))
+ {
+ unsigned int i;
+ for (i = 0; i < count; ++i)
+ {
+ BinIOSwap8(src, dst);
+ src += 8;
+ dst += 8;
+ }
+ }
+ else
+ {
+ memcpy(dst, src, 8 * count);
+ }
+}
+
+void BinIOInitFormatCursor(struct BinIOFormatCursor *cursor,
+ const char *format)
+{
+ cursor->cursor = format;
+ cursor->byte_order = BinIO_HOST_BYTE_ORDER;
+ cursor->count = -1;
+}
+
+int BinIONextChar(void *context,
+ struct BinIOFormatCursor *cursor,
+ BinIOProcessFunction func)
+{
+ int count, value;
+ int c;
+ switch (c = *(cursor->cursor)++)
+ {
+ case BinIO_LITTLE_ENDIAN_BYTE_ORDER:
+ case BinIO_BIG_ENDIAN_BYTE_ORDER:
+ case BinIO_HOST_BYTE_ORDER:
+ case BinIO_NETWORK_BYTE_ORDER:
+ cursor->byte_order = c;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ count = cursor->count;
+ value = c - '0';
+ if (count == -1)
+ {
+ cursor->count = value;
+ }
+ else
+ {
+ cursor->count = (count * 10) + value;
+ }
+ break;
+
+ case BinIO_TYPE_IGNORE_BYTE:
+ case BinIO_TYPE_BYTE:
+ case BinIO_TYPE_INT16:
+ case BinIO_TYPE_INT32:
+ case BinIO_TYPE_INT64:
+ case BinIO_TYPE_FLOAT32:
+ case BinIO_TYPE_FLOAT64:
+ func(context, c, cursor->byte_order, cursor->count);
+ cursor->byte_order = BinIO_HOST_BYTE_ORDER;
+ cursor->count = -1;
+ break;
+
+ case ' ': case '\t': case '\r': case '\n':
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+extern void BinIOCountBytes(void *context, int type, int byte_order, int count)
+{
+ size_t type_size = 0;
+
+ if (count == -1)
+ {
+ count = 1;
+ }
+
+ switch (type)
+ {
+ case BinIO_TYPE_IGNORE_BYTE: type_size = 1; break;
+ case BinIO_TYPE_BYTE: type_size = 1; break;
+ case BinIO_TYPE_INT16: type_size = 2; break;
+ case BinIO_TYPE_INT32: type_size = 4; break;
+ case BinIO_TYPE_INT64: type_size = 8; break;
+ case BinIO_TYPE_FLOAT32: type_size = 4; break;
+ case BinIO_TYPE_FLOAT64: type_size = 8; break;
+ }
+
+ *(size_t*)context += type_size * count;
+}
+
+extern size_t BinIOFormatByteCount(const char *format)
+{
+ struct BinIOFormatCursor cursor;
+ size_t n_bytes = 0;
+
+ BinIOInitFormatCursor(&cursor, format);
+
+ while (BinIONextChar(&n_bytes, &cursor, BinIOCountBytes)) {}
+
+ return n_bytes;
+}
--- /dev/null
+#ifndef private_h
+#define private_h
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#define BinIO_TYPE_IGNORE_BYTE 'x'
+#define BinIO_TYPE_BYTE 'b'
+#define BinIO_TYPE_INT16 's'
+#define BinIO_TYPE_INT32 'i'
+#define BinIO_TYPE_INT64 'l'
+#define BinIO_TYPE_FLOAT32 'f'
+#define BinIO_TYPE_FLOAT64 'd'
+
+#define BinIO_LITTLE_ENDIAN_BYTE_ORDER 'L'
+#define BinIO_BIG_ENDIAN_BYTE_ORDER 'B'
+#define BinIO_HOST_BYTE_ORDER 'H'
+#define BinIO_NETWORK_BYTE_ORDER 'N'
+
+#if defined(BinIO_STDINT_HEADER)
+#include BinIO_STDINT_HEADER
+typedef float float32_t;
+typedef double float64_t;
+#else
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+#ifdef WIN32
+ typedef unsigned __int64 uint64_t;
+#else
+ typedef unsigned long long uint64_t;
+#endif
+typedef float float32_t;
+typedef double float64_t;
+#endif
+
+#ifndef BinIO_INLINE
+#if defined(__GNUC__)
+#define BinIO_INLINE static inline
+#else
+#define BinIO_INLINE static
+#endif
+#endif
+
+#ifndef BinIO_BYTE_ORDER
+#if defined(__ppc__) || defined(__POWERPC__)
+#define BinIO_BYTE_ORDER BinIO_BIG_ENDIAN_BYTE_ORDER
+#else
+#define BinIO_BYTE_ORDER BinIO_LITTLE_ENDIAN_BYTE_ORDER
+#endif
+#endif
+
+BinIO_INLINE void BinIOSwap1(const uint8_t *src, uint8_t *dst)
+{
+ *dst = *src;
+}
+
+BinIO_INLINE void BinIOSwap2(const uint8_t *src, uint8_t *dst)
+{
+ *(dst + 1) = *(src + 0);
+ *(dst + 0) = *(src + 1);
+}
+
+BinIO_INLINE void BinIOSwap4(const uint8_t *src, uint8_t *dst)
+{
+ *(dst + 3) = *(src + 0);
+ *(dst + 2) = *(src + 1);
+ *(dst + 1) = *(src + 2);
+ *(dst + 0) = *(src + 3);
+}
+
+BinIO_INLINE void BinIOSwap8(const uint8_t *src, uint8_t *dst)
+{
+ *(dst + 7) = *(src + 0);
+ *(dst + 6) = *(src + 1);
+ *(dst + 5) = *(src + 2);
+ *(dst + 4) = *(src + 3);
+ *(dst + 3) = *(src + 4);
+ *(dst + 2) = *(src + 5);
+ *(dst + 1) = *(src + 6);
+ *(dst + 0) = *(src + 7);
+}
+
+BinIO_INLINE int BinIONormalizeByteOrder(int byte_order)
+{
+ if (byte_order == BinIO_HOST_BYTE_ORDER)
+ {
+ byte_order = BinIO_BYTE_ORDER;
+ }
+ else if (byte_order == BinIO_NETWORK_BYTE_ORDER)
+ {
+ byte_order = BinIO_BIG_ENDIAN_BYTE_ORDER;
+ }
+
+ return byte_order;
+}
+
+extern void BinIOConvert1(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count);
+extern void BinIOConvert2(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count);
+extern void BinIOConvert4(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count);
+extern void BinIOConvert8(int from_byte_order, int to_byte_order,
+ const uint8_t *src, uint8_t *dst,
+ unsigned int count);
+
+struct BinIOFormatCursor
+{
+ const char *cursor;
+ int byte_order;
+ int count;
+};
+
+typedef void (*BinIOProcessFunction)(void *context,
+ int type,
+ int byte_order,
+ int count);
+
+extern void BinIOInitFormatCursor(struct BinIOFormatCursor *cursor,
+ const char *format);
+
+extern int BinIONextChar(void *context,
+ struct BinIOFormatCursor *cursor,
+ BinIOProcessFunction func);
+
+extern void BinIOCountBytes(void *context, int type, int byte_order, int count);
+
+extern size_t BinIOFormatByteCount(const char *format);
+
+#endif
--- /dev/null
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_LUGARU ICON "lugaru.ico"
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Lugaru.rc
+//
+#define IDI_LUGARU 104
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
--- /dev/null
+#include <stdlib.h>
+
+#include "binio.h"
+#include "private.h"
+#include "unpack_private.h"
+
+void unpackf(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfunpackf(stdin, format, args);
+ va_end(args);
+}
+
+void sunpackf(const void *buffer, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vsunpackf(buffer, format, args);
+ va_end(args);
+}
+
+void funpackf(FILE *file, const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfunpackf(file, format, args);
+ va_end(args);
+}
+
+void vsunpackf(const void *buffer, const char *format, va_list args)
+{
+ struct BinIOFormatCursor cursor;
+ struct BinIOUnpackContext context;
+
+ BinIOInitFormatCursor(&cursor, format);
+
+ context.data = (const unsigned char*)buffer;
+ context.args = args;
+
+ while (BinIONextChar(&context, &cursor, BinIOUnpack)) {}
+}
+
+void vfunpackf(FILE *file, const char *format, va_list args)
+{
+ size_t n_bytes = BinIOFormatByteCount(format);
+ void* buffer = malloc(n_bytes);
+ fread(buffer, n_bytes, 1, file);
+
+ vsunpackf(buffer, format, args);
+
+ free(buffer);
+}
--- /dev/null
+#include "unpack_private.h"
+
+extern void BinIOUnpack(void *context, int type, int byte_order, int count)
+{
+ struct BinIOUnpackContext *ctx = (struct BinIOUnpackContext*)context;
+ if (count == -1)
+ {
+ count = 1;
+ }
+
+ switch (type)
+ {
+ case BinIO_TYPE_IGNORE_BYTE: ctx->data += 1 * count; break;
+ case BinIO_TYPE_BYTE: BinIOConvert1(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 1 * count; break;
+ case BinIO_TYPE_INT16: BinIOConvert2(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 2 * count; break;
+ case BinIO_TYPE_INT32: BinIOConvert4(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 4 * count; break;
+ case BinIO_TYPE_INT64: BinIOConvert8(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 8 * count; break;
+ case BinIO_TYPE_FLOAT32: BinIOConvert4(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 4 * count; break;
+ case BinIO_TYPE_FLOAT64: BinIOConvert8(byte_order, BinIO_HOST_BYTE_ORDER, ctx->data, va_arg(ctx->args, uint8_t *), count); ctx->data += 8 * count; break;
+ }
+}
--- /dev/null
+#ifndef unpack_private_h
+#define unpack_private_h
+
+#include "private.h"
+
+struct BinIOUnpackContext
+{
+ const uint8_t *data;
+ va_list args;
+};
+
+extern void BinIOUnpack(void *context, int type, int byte_order, int count);
+
+#endif
--- /dev/null
+#if !defined(WINCOMPAT_INCLUDED) && !defined(PLATFORM_WINDOWS) && !defined(WIN32) && !defined(WINDOWS) && !defined(__WIN32__)
+#define WINCOMPAT_INCLUDED
+
+/**
+ *
+ * Author: Magnus Naeslund (mag@fbab.net, mag@bahnhof.se)
+ * (c) 2000 Magnus Naeslund, all rights reserved
+ *
+ */
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef TRUE
+ #define TRUE 1
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+#define _kbhit kbhit
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+#define Sleep(x) usleep((x)*1000)
+
+static int inited=0;
+static struct termios ori;
+
+static void tcatexit(){
+ tcsetattr(0,0,&ori);
+}
+
+static void init_terminal(){
+ struct termios t;
+ tcgetattr(0,&t);
+ tcgetattr(0,&ori);
+ t.c_lflag &= ~(ICANON);
+ tcsetattr(0,0,&t);
+ atexit(tcatexit);
+}
+
+static inline int kbhit(){
+ fd_set rfds;
+ struct timeval tv;
+
+ if (!inited){
+ inited=1;
+ init_terminal();
+ }
+
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 10*1000;
+ return select(1, &rfds, NULL, NULL, &tv)>0;
+}
+
+static inline int getch(){
+ fd_set rfds;
+
+ if (!inited){
+ inited=1;
+ init_terminal();
+ }
+
+ FD_ZERO(&rfds);
+ FD_SET(0, &rfds);
+ if (select(1, &rfds, NULL, NULL, NULL)>0)
+ return getchar();
+ else{
+ printf("wincompat.h: select() on fd 0 failed\n");
+ return 0xDeadBeef;
+ }
+}
+
+#endif