summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AppHeaders/CSBase.h97
-rw-r--r--AppHeaders/DVector.h372
-rw-r--r--AppHeaders/SpriteControl.h30
-rw-r--r--AppHeaders/aggregate_de.h36
-rw-r--r--AppHeaders/basedefs_de.h849
-rw-r--r--AppHeaders/basetypes_de.h412
-rw-r--r--AppHeaders/client_de.h1152
-rw-r--r--AppHeaders/clientshell_de.h144
-rw-r--r--AppHeaders/common_de.h70
-rw-r--r--AppHeaders/cpp_aggregate_de.h67
-rw-r--r--AppHeaders/cpp_client_de.h5
-rw-r--r--AppHeaders/cpp_clientshell_de.h266
-rw-r--r--AppHeaders/cpp_engineobjects_de.cpp29
-rw-r--r--AppHeaders/cpp_engineobjects_de.h155
-rw-r--r--AppHeaders/cpp_server_de.h5
-rw-r--r--AppHeaders/cpp_servershell_de.h266
-rw-r--r--AppHeaders/de_client.h21
-rw-r--r--AppHeaders/de_codes.h251
-rw-r--r--AppHeaders/de_server.h22
-rw-r--r--AppHeaders/dlink.h124
-rw-r--r--AppHeaders/dstream.h67
-rw-r--r--AppHeaders/engineobjects.c869
-rw-r--r--AppHeaders/engineobjects_de.h62
-rw-r--r--AppHeaders/generic_msg_de.h72
-rw-r--r--AppHeaders/lmessage.h123
-rw-r--r--AppHeaders/matrix_ops.h219
-rw-r--r--AppHeaders/physics_lt.h99
-rw-r--r--AppHeaders/server_de.h932
-rw-r--r--AppHeaders/serverobj_de.h539
-rw-r--r--AppHeaders/servershell_de.h112
-rw-r--r--AppHeaders/specialeffect_de.h11
-rw-r--r--Blood2Serv/CoolServ.cpp324
-rw-r--r--Blood2Serv/CoolServ.dsp233
-rw-r--r--Blood2Serv/CoolServ.h56
-rw-r--r--Blood2Serv/CoolServ.ncbbin0 -> 50176 bytes
-rw-r--r--Blood2Serv/CoolServ.optbin0 -> 53760 bytes
-rw-r--r--Blood2Serv/CoolServ.rc823
-rw-r--r--Blood2Serv/GameServDlg.cpp1478
-rw-r--r--Blood2Serv/GameServDlg.h179
-rw-r--r--Blood2Serv/MyGameSpyMgr.cpp173
-rw-r--r--Blood2Serv/MyGameSpyMgr.h39
-rw-r--r--Blood2Serv/NetDefs.h144
-rw-r--r--Blood2Serv/NetStart.cpp3228
-rw-r--r--Blood2Serv/NetStart.h88
-rw-r--r--Blood2Serv/Res/CoolServ.icobin0 -> 4710 bytes
-rw-r--r--Blood2Serv/Res/CoolServ.rc213
-rw-r--r--Blood2Serv/Res/game1.bmpbin0 -> 5018 bytes
-rw-r--r--Blood2Serv/Res/vssver.sccbin0 -> 80 bytes
-rw-r--r--Blood2Serv/RezFind.cpp206
-rw-r--r--Blood2Serv/RezFind.h27
-rw-r--r--Blood2Serv/ServerUtils.cpp195
-rw-r--r--Blood2Serv/ServerUtils.h35
-rw-r--r--Blood2Serv/Sparam.cpp130
-rw-r--r--Blood2Serv/Sparam.h29
-rw-r--r--Blood2Serv/StdAfx.cpp6
-rw-r--r--Blood2Serv/StdAfx.h26
-rw-r--r--Blood2Serv/Utils.cpp39
-rw-r--r--Blood2Serv/Utils.h11
-rw-r--r--Blood2Serv/bitmap1.bmpbin0 -> 5018 bytes
-rw-r--r--Blood2Serv/resource.h193
-rw-r--r--ClientRes/AddOn.bmpbin0 -> 5018 bytes
-rw-r--r--ClientRes/ClientRes.dsp161
-rw-r--r--ClientRes/ClientRes.rc1968
-rw-r--r--ClientRes/bitmap1.bmpbin0 -> 5018 bytes
-rw-r--r--ClientRes/credits.txt516
-rw-r--r--ClientRes/credits_ao.txt168
-rw-r--r--ClientShellDLL/BaseLineSystemFX.cpp98
-rw-r--r--ClientShellDLL/BaseLineSystemFX.h37
-rw-r--r--ClientShellDLL/BaseParticleSystemFX.cpp174
-rw-r--r--ClientShellDLL/BaseParticleSystemFX.h65
-rw-r--r--ClientShellDLL/BloodClientShell.cpp9406
-rw-r--r--ClientShellDLL/BloodClientShell.h691
-rw-r--r--ClientShellDLL/BloodSplatFX.cpp218
-rw-r--r--ClientShellDLL/BloodSplatFX.h85
-rw-r--r--ClientShellDLL/BloodTrailFX.cpp88
-rw-r--r--ClientShellDLL/BloodTrailFX.h67
-rw-r--r--ClientShellDLL/BloodTrailSegmentFX.cpp273
-rw-r--r--ClientShellDLL/BloodTrailSegmentFX.h73
-rw-r--r--ClientShellDLL/BulletImpactSFX.cpp88
-rw-r--r--ClientShellDLL/BulletImpactSFX.h66
-rw-r--r--ClientShellDLL/CameraFX.h76
-rw-r--r--ClientShellDLL/CastLineFX.cpp123
-rw-r--r--ClientShellDLL/CastLineFX.h61
-rw-r--r--ClientShellDLL/ClientShellDLL.dsp984
-rw-r--r--ClientShellDLL/ClientShellDLL.rc105
-rw-r--r--ClientShellDLL/ClientUtilities.cpp304
-rw-r--r--ClientShellDLL/ClientUtilities.h58
-rw-r--r--ClientShellDLL/CommLink.cpp420
-rw-r--r--ClientShellDLL/CommLink.h105
-rw-r--r--ClientShellDLL/ConfigMgr.cpp647
-rw-r--r--ClientShellDLL/ConfigMgr.h182
-rw-r--r--ClientShellDLL/Credits.cpp995
-rw-r--r--ClientShellDLL/Credits.h221
-rw-r--r--ClientShellDLL/CreditsWin.cpp48
-rw-r--r--ClientShellDLL/CreditsWin.h26
-rw-r--r--ClientShellDLL/ExplosionFX.cpp8341
-rw-r--r--ClientShellDLL/ExplosionFX.h609
-rw-r--r--ClientShellDLL/FlashlightFX.cpp144
-rw-r--r--ClientShellDLL/FlashlightFX.h37
-rw-r--r--ClientShellDLL/FragInfo.cpp924
-rw-r--r--ClientShellDLL/FragInfo.h120
-rw-r--r--ClientShellDLL/GameStates.cpp264
-rw-r--r--ClientShellDLL/GameWeapons.cpp538
-rw-r--r--ClientShellDLL/GameWeapons.h320
-rw-r--r--ClientShellDLL/GibFX.h151
-rw-r--r--ClientShellDLL/IKChainFX.cpp222
-rw-r--r--ClientShellDLL/IKChainFX.h77
-rw-r--r--ClientShellDLL/IpMgr.cpp563
-rw-r--r--ClientShellDLL/IpMgr.h126
-rw-r--r--ClientShellDLL/KeyFixes.cpp106
-rw-r--r--ClientShellDLL/KeyFixes.h7
-rw-r--r--ClientShellDLL/LaserBeamFX.cpp257
-rw-r--r--ClientShellDLL/LaserBeamFX.h73
-rw-r--r--ClientShellDLL/LaserFX.cpp233
-rw-r--r--ClientShellDLL/LaserFX.h61
-rw-r--r--ClientShellDLL/LightFX.cpp404
-rw-r--r--ClientShellDLL/LightFX.h146
-rw-r--r--ClientShellDLL/LightningFX.cpp371
-rw-r--r--ClientShellDLL/LightningFX.h95
-rw-r--r--ClientShellDLL/LightningSegmentFX.cpp142
-rw-r--r--ClientShellDLL/LightningSegmentFX.h75
-rw-r--r--ClientShellDLL/LoadSave.cpp454
-rw-r--r--ClientShellDLL/LoadSave.h61
-rw-r--r--ClientShellDLL/LoadScreenData.cpp413
-rw-r--r--ClientShellDLL/LoadScreenData.h37
-rw-r--r--ClientShellDLL/MainMenus.cpp1174
-rw-r--r--ClientShellDLL/MainMenus.h267
-rw-r--r--ClientShellDLL/MarkSFX.cpp169
-rw-r--r--ClientShellDLL/MarkSFX.h79
-rw-r--r--ClientShellDLL/Menu.cpp2506
-rw-r--r--ClientShellDLL/Menu.h294
-rw-r--r--ClientShellDLL/MenuBase.cpp851
-rw-r--r--ClientShellDLL/MenuBase.h230
-rw-r--r--ClientShellDLL/MenuBloodBath.cpp131
-rw-r--r--ClientShellDLL/MenuBloodBath.h35
-rw-r--r--ClientShellDLL/MenuCharacter.cpp851
-rw-r--r--ClientShellDLL/MenuCharacter.h128
-rw-r--r--ClientShellDLL/MenuCharacterFiles.cpp150
-rw-r--r--ClientShellDLL/MenuCharacterFiles.h53
-rw-r--r--ClientShellDLL/MenuCharacterSelect.cpp82
-rw-r--r--ClientShellDLL/MenuCharacterSelect.h30
-rw-r--r--ClientShellDLL/MenuCommands.h80
-rw-r--r--ClientShellDLL/MenuControls.cpp656
-rw-r--r--ClientShellDLL/MenuControls.h76
-rw-r--r--ClientShellDLL/MenuCustomLevel.cpp150
-rw-r--r--ClientShellDLL/MenuCustomLevel.h37
-rw-r--r--ClientShellDLL/MenuDifficulty.cpp90
-rw-r--r--ClientShellDLL/MenuDifficulty.h42
-rw-r--r--ClientShellDLL/MenuDisplay.cpp578
-rw-r--r--ClientShellDLL/MenuDisplay.h92
-rw-r--r--ClientShellDLL/MenuJoystick.cpp253
-rw-r--r--ClientShellDLL/MenuJoystick.h53
-rw-r--r--ClientShellDLL/MenuJoystickAxis.cpp1096
-rw-r--r--ClientShellDLL/MenuJoystickAxis.h241
-rw-r--r--ClientShellDLL/MenuKeyboard.cpp53
-rw-r--r--ClientShellDLL/MenuKeyboard.h30
-rw-r--r--ClientShellDLL/MenuLoadGame.cpp95
-rw-r--r--ClientShellDLL/MenuLoadGame.h31
-rw-r--r--ClientShellDLL/MenuMain.cpp109
-rw-r--r--ClientShellDLL/MenuMain.h27
-rw-r--r--ClientShellDLL/MenuMouse.cpp224
-rw-r--r--ClientShellDLL/MenuMouse.h51
-rw-r--r--ClientShellDLL/MenuOptions.cpp104
-rw-r--r--ClientShellDLL/MenuOptions.h27
-rw-r--r--ClientShellDLL/MenuSaveGame.cpp73
-rw-r--r--ClientShellDLL/MenuSaveGame.h31
-rw-r--r--ClientShellDLL/MenuSinglePlayer.cpp121
-rw-r--r--ClientShellDLL/MenuSinglePlayer.h33
-rw-r--r--ClientShellDLL/MenuSound.cpp225
-rw-r--r--ClientShellDLL/MenuSound.h50
-rw-r--r--ClientShellDLL/MessageBoxHandler.cpp38
-rw-r--r--ClientShellDLL/MessageBoxHandler.h22
-rw-r--r--ClientShellDLL/MessageMgr.cpp1100
-rw-r--r--ClientShellDLL/MessageMgr.h218
-rw-r--r--ClientShellDLL/MoveMgr.cpp1626
-rw-r--r--ClientShellDLL/MoveMgr.h186
-rw-r--r--ClientShellDLL/Music.cpp437
-rw-r--r--ClientShellDLL/Music.h80
-rw-r--r--ClientShellDLL/NetInfo.cpp670
-rw-r--r--ClientShellDLL/NetInfo.h181
-rw-r--r--ClientShellDLL/NetStart.cpp4957
-rw-r--r--ClientShellDLL/NetStart.h83
-rw-r--r--ClientShellDLL/NewStatusBar.cpp1561
-rw-r--r--ClientShellDLL/NewStatusBar.h310
-rw-r--r--ClientShellDLL/ObjectFX.cpp3811
-rw-r--r--ClientShellDLL/ObjectFX.h213
-rw-r--r--ClientShellDLL/ParticleExplosionFX.cpp459
-rw-r--r--ClientShellDLL/ParticleExplosionFX.h160
-rw-r--r--ClientShellDLL/ParticleStreamFX.cpp280
-rw-r--r--ClientShellDLL/ParticleStreamFX.h140
-rw-r--r--ClientShellDLL/ParticleSystemFX.cpp209
-rw-r--r--ClientShellDLL/ParticleSystemFX.h76
-rw-r--r--ClientShellDLL/PickupObjectFX.cpp77
-rw-r--r--ClientShellDLL/PickupObjectFX.h38
-rw-r--r--ClientShellDLL/PlayerCamera.cpp897
-rw-r--r--ClientShellDLL/PlayerCamera.h237
-rw-r--r--ClientShellDLL/PolyGridFX.cpp490
-rw-r--r--ClientShellDLL/PolyGridFX.h154
-rw-r--r--ClientShellDLL/RainFX.cpp294
-rw-r--r--ClientShellDLL/RainFX.h80
-rw-r--r--ClientShellDLL/RippleFX.cpp177
-rw-r--r--ClientShellDLL/RippleFX.h82
-rw-r--r--ClientShellDLL/SFXMgr.cpp1671
-rw-r--r--ClientShellDLL/SFXMgr.h66
-rw-r--r--ClientShellDLL/SharedResourceMgr.cpp173
-rw-r--r--ClientShellDLL/SharedResourceMgr.h73
-rw-r--r--ClientShellDLL/ShellCasingFX.cpp295
-rw-r--r--ClientShellDLL/ShellCasingFX.h73
-rw-r--r--ClientShellDLL/SmokeFX.cpp140
-rw-r--r--ClientShellDLL/SmokeFX.h103
-rw-r--r--ClientShellDLL/SmokeImpactFX.cpp201
-rw-r--r--ClientShellDLL/SmokeImpactFX.h95
-rw-r--r--ClientShellDLL/SmokePuffFX.cpp188
-rw-r--r--ClientShellDLL/SmokePuffFX.h100
-rw-r--r--ClientShellDLL/SmokeTrailFX.cpp108
-rw-r--r--ClientShellDLL/SmokeTrailFX.h70
-rw-r--r--ClientShellDLL/SmokeTrailSegmentFX.cpp256
-rw-r--r--ClientShellDLL/SmokeTrailSegmentFX.h86
-rw-r--r--ClientShellDLL/Sparam.cpp131
-rw-r--r--ClientShellDLL/Sparam.h29
-rw-r--r--ClientShellDLL/SparksFX.cpp183
-rw-r--r--ClientShellDLL/SparksFX.h86
-rw-r--r--ClientShellDLL/SpecialFX.h105
-rw-r--r--ClientShellDLL/SpecialFXList.cpp90
-rw-r--r--ClientShellDLL/SpecialFXList.h111
-rw-r--r--ClientShellDLL/Splash.cpp290
-rw-r--r--ClientShellDLL/Splash.h36
-rw-r--r--ClientShellDLL/SplashFX.cpp136
-rw-r--r--ClientShellDLL/SplashFX.h95
-rw-r--r--ClientShellDLL/StatusBar.cpp2560
-rw-r--r--ClientShellDLL/StatusBar.h473
-rw-r--r--ClientShellDLL/SurfaceFragmentFX.cpp185
-rw-r--r--ClientShellDLL/SurfaceFragmentFX.h94
-rw-r--r--ClientShellDLL/TheVoice.cpp408
-rw-r--r--ClientShellDLL/TheVoice.h114
-rw-r--r--ClientShellDLL/TracerFX.cpp172
-rw-r--r--ClientShellDLL/TracerFX.h76
-rw-r--r--ClientShellDLL/TripLaserFX.cpp111
-rw-r--r--ClientShellDLL/TripLaserFX.h61
-rw-r--r--ClientShellDLL/VKDefs.h152
-rw-r--r--ClientShellDLL/ViewWeapon.cpp1561
-rw-r--r--ClientShellDLL/ViewWeapon.h230
-rw-r--r--ClientShellDLL/VoiceMgr.cpp863
-rw-r--r--ClientShellDLL/VoiceMgr.h209
-rw-r--r--ClientShellDLL/VolumeBrushFX.h73
-rw-r--r--ClientShellDLL/WarpGateFX.cpp433
-rw-r--r--ClientShellDLL/WarpGateFX.h179
-rw-r--r--ClientShellDLL/WeaponFX.cpp1146
-rw-r--r--ClientShellDLL/WeaponFX.h144
-rw-r--r--ClientShellDLL/WeaponPowerupFX.cpp126
-rw-r--r--ClientShellDLL/WeaponPowerupFX.h72
-rw-r--r--ClientShellDLL/WinUtil.cpp254
-rw-r--r--ClientShellDLL/WinUtil.h42
-rw-r--r--ClientShellDLL/client_physics.cpp180
-rw-r--r--ClientShellDLL/client_physics.h61
-rw-r--r--ClientShellDLL/debugline.cpp77
-rw-r--r--ClientShellDLL/debugline.h55
-rw-r--r--ClientShellDLL/gibfx.cpp576
-rw-r--r--ClientShellDLL/plasma.h10
-rw-r--r--ClientShellDLL/plasma1.cpp12
-rw-r--r--ClientShellDLL/resource.h15
-rw-r--r--ClientShellDLL/stack.h118
-rw-r--r--ClientShellDLL/viewcreature.cpp222
-rw-r--r--ClientShellDLL/viewcreature.h55
-rw-r--r--EULA.txt38
-rw-r--r--Misc/AbstractIO.h127
-rw-r--r--Misc/ArchiveIO.h51
-rw-r--r--Misc/BareList.h78
-rw-r--r--Misc/BareList.libbin0 -> 2552 bytes
-rw-r--r--Misc/CompressedIO.h122
-rw-r--r--Misc/CoolFont.h163
-rw-r--r--Misc/Dynarray.h624
-rw-r--r--Misc/FastArray.h457
-rw-r--r--Misc/FastLinkList.h73
-rw-r--r--Misc/FileIO.h68
-rw-r--r--Misc/GameSpyMgr.h197
-rw-r--r--Misc/GameSpyMgr.libbin0 -> 32084 bytes
-rw-r--r--Misc/GoodLinkList.h370
-rw-r--r--Misc/Helpers.h47
-rw-r--r--Misc/LTGUIColumnTextCtrl.h95
-rw-r--r--Misc/LTGUICommandHandler.h30
-rw-r--r--Misc/LTGUICtrl.h86
-rw-r--r--Misc/LTGUIEditCtrl.h92
-rw-r--r--Misc/LTGUIFadeColorCtrl.h49
-rw-r--r--Misc/LTGUIFadeItemCtrl.h72
-rw-r--r--Misc/LTGUIFont.h59
-rw-r--r--Misc/LTGUIListCtrl.h86
-rw-r--r--Misc/LTGUIMessageBox.h76
-rw-r--r--Misc/LTGUIMgr.h41
-rw-r--r--Misc/LTGUIMgr.libbin0 -> 256370 bytes
-rw-r--r--Misc/LTGUIOnOffCtrl.h45
-rw-r--r--Misc/LTGUISliderCtrl.h97
-rw-r--r--Misc/LTGUITextItemCtrl.h99
-rw-r--r--Misc/LinkList.h374
-rw-r--r--Misc/LithException.h50
-rw-r--r--Misc/Memory.h11
-rw-r--r--Misc/MemoryIO.h68
-rw-r--r--Misc/MenuBase.h279
-rw-r--r--Misc/MoRect.h70
-rw-r--r--Misc/MultiLinkList.h368
-rw-r--r--Misc/ObjectBank.h58
-rw-r--r--Misc/StdLith.h52
-rw-r--r--Misc/StdLith.libbin0 -> 50916 bytes
-rw-r--r--Misc/StdLithDefs.h71
-rw-r--r--Misc/Stdafx.h7
-rw-r--r--Misc/StringHolder.h81
-rw-r--r--Misc/VKDefs.h152
-rw-r--r--Misc/glink.h36
-rw-r--r--Misc/object_bank.h140
-rw-r--r--Misc/server_interface.h154
-rw-r--r--Misc/struct_bank.h162
-rw-r--r--ObjectDLL/AIScriptList.h289
-rw-r--r--ObjectDLL/AI_Mgr.cpp7019
-rw-r--r--ObjectDLL/AI_Mgr.h513
-rw-r--r--ObjectDLL/AI_Shared.CPP2290
-rw-r--r--ObjectDLL/AI_Shared.h95
-rw-r--r--ObjectDLL/AmmoPickups.cpp285
-rw-r--r--ObjectDLL/AmmoPickups.h118
-rw-r--r--ObjectDLL/AncientOne.cpp491
-rw-r--r--ObjectDLL/AncientOne.h61
-rw-r--r--ObjectDLL/AncientOneTentacle.cpp623
-rw-r--r--ObjectDLL/AncientOneTentacle.h72
-rw-r--r--ObjectDLL/Anim_Sound.cpp607
-rw-r--r--ObjectDLL/Anim_Sound.h390
-rw-r--r--ObjectDLL/B2BaseClass.cpp244
-rw-r--r--ObjectDLL/B2BaseClass.h69
-rw-r--r--ObjectDLL/BaseCharacter.cpp461
-rw-r--r--ObjectDLL/BaseCharacter.h87
-rw-r--r--ObjectDLL/BirdAI.cpp515
-rw-r--r--ObjectDLL/BirdAI.h39
-rw-r--r--ObjectDLL/BloodServerShell.cpp2129
-rw-r--r--ObjectDLL/BloodServerShell.h147
-rw-r--r--ObjectDLL/BulletImpactSFX.cpp80
-rw-r--r--ObjectDLL/BulletImpactSFX.h31
-rw-r--r--ObjectDLL/CVarTrack.h113
-rw-r--r--ObjectDLL/CalebAI.cpp130
-rw-r--r--ObjectDLL/CalebAI.h38
-rw-r--r--ObjectDLL/CameraObj.cpp660
-rw-r--r--ObjectDLL/CameraObj.h75
-rw-r--r--ObjectDLL/CameraSpot.cpp231
-rw-r--r--ObjectDLL/CameraSpot.h44
-rw-r--r--ObjectDLL/ChosenSounds.h102
-rw-r--r--ObjectDLL/CinematicTrigger.cpp506
-rw-r--r--ObjectDLL/CinematicTrigger.h55
-rw-r--r--ObjectDLL/CivilianAI.cpp779
-rw-r--r--ObjectDLL/CivilianAI.h66
-rw-r--r--ObjectDLL/ClientCastLineSFX.cpp45
-rw-r--r--ObjectDLL/ClientCastLineSFX.h25
-rw-r--r--ObjectDLL/ClientExplosionSFX.cpp452
-rw-r--r--ObjectDLL/ClientExplosionSFX.h103
-rw-r--r--ObjectDLL/ClientGibFX.cpp124
-rw-r--r--ObjectDLL/ClientGibFX.h45
-rw-r--r--ObjectDLL/ClientLaserBeamSFX.cpp234
-rw-r--r--ObjectDLL/ClientLaserBeamSFX.h68
-rw-r--r--ObjectDLL/ClientLaserFX.cpp40
-rw-r--r--ObjectDLL/ClientLaserFX.h25
-rw-r--r--ObjectDLL/ClientLightFX.cpp703
-rw-r--r--ObjectDLL/ClientLightFX.h152
-rw-r--r--ObjectDLL/ClientLightningSFX.cpp251
-rw-r--r--ObjectDLL/ClientLightningSFX.h74
-rw-r--r--ObjectDLL/ClientMarkSFX.cpp145
-rw-r--r--ObjectDLL/ClientMarkSFX.h44
-rw-r--r--ObjectDLL/ClientParticleStreamSFX.cpp332
-rw-r--r--ObjectDLL/ClientParticleStreamSFX.h75
-rw-r--r--ObjectDLL/ClientSFX.cpp50
-rw-r--r--ObjectDLL/ClientSFX.h29
-rw-r--r--ObjectDLL/ClientSmokeTrail.cpp41
-rw-r--r--ObjectDLL/ClientSmokeTrail.h24
-rw-r--r--ObjectDLL/ClientSparksSFX.cpp97
-rw-r--r--ObjectDLL/ClientSparksSFX.h31
-rw-r--r--ObjectDLL/ClientSplashSFX.cpp94
-rw-r--r--ObjectDLL/ClientSplashSFX.h30
-rw-r--r--ObjectDLL/ClientSplatFX.cpp77
-rw-r--r--ObjectDLL/ClientSplatFX.h29
-rw-r--r--ObjectDLL/ClientTracer.cpp76
-rw-r--r--ObjectDLL/ClientTracer.h29
-rw-r--r--ObjectDLL/ClientWarpGateSFX.cpp611
-rw-r--r--ObjectDLL/ClientWarpGateSFX.h92
-rw-r--r--ObjectDLL/ClientWeaponSFX.cpp90
-rw-r--r--ObjectDLL/ClientWeaponSFX.h77
-rw-r--r--ObjectDLL/ConversationStrings.h217
-rw-r--r--ObjectDLL/ConversationTrigger.cpp359
-rw-r--r--ObjectDLL/ConversationTrigger.h47
-rw-r--r--ObjectDLL/CultistAI.cpp748
-rw-r--r--ObjectDLL/CultistAI.h64
-rw-r--r--ObjectDLL/DeathShroud.cpp505
-rw-r--r--ObjectDLL/DeathShroud.h61
-rw-r--r--ObjectDLL/Debris.cpp533
-rw-r--r--ObjectDLL/Debris.h90
-rw-r--r--ObjectDLL/DefenseGlobeAI.cpp424
-rw-r--r--ObjectDLL/DefenseGlobeAI.h150
-rw-r--r--ObjectDLL/DefenseGlobeLegs.cpp184
-rw-r--r--ObjectDLL/DefenseGlobeLegs.h41
-rw-r--r--ObjectDLL/Destructable.cpp1341
-rw-r--r--ObjectDLL/Destructable.h216
-rw-r--r--ObjectDLL/DestructableBrush.cpp427
-rw-r--r--ObjectDLL/DestructableBrush.h54
-rw-r--r--ObjectDLL/DestructableModel.cpp1055
-rw-r--r--ObjectDLL/DestructableModel.h90
-rw-r--r--ObjectDLL/DetailSprite.cpp358
-rw-r--r--ObjectDLL/DetailSprite.h67
-rw-r--r--ObjectDLL/Door.cpp1189
-rw-r--r--ObjectDLL/Door.h136
-rw-r--r--ObjectDLL/DrudgeLord.cpp434
-rw-r--r--ObjectDLL/DrudgeLord.h49
-rw-r--r--ObjectDLL/EnhancedGideon.cpp1098
-rw-r--r--ObjectDLL/EnhancedGideon.h84
-rw-r--r--ObjectDLL/ExitHint.cpp35
-rw-r--r--ObjectDLL/ExitHint.h51
-rw-r--r--ObjectDLL/ExitTrigger.cpp241
-rw-r--r--ObjectDLL/ExitTrigger.h43
-rw-r--r--ObjectDLL/Explosion.cpp773
-rw-r--r--ObjectDLL/Explosion.h123
-rw-r--r--ObjectDLL/Fanatic.cpp837
-rw-r--r--ObjectDLL/Fanatic.h60
-rw-r--r--ObjectDLL/FileCaching.h1197
-rw-r--r--ObjectDLL/FireFX.cpp580
-rw-r--r--ObjectDLL/FireFX.h76
-rw-r--r--ObjectDLL/FlagObjects.cpp766
-rw-r--r--ObjectDLL/FlagObjects.h136
-rw-r--r--ObjectDLL/GabriellaAI.cpp584
-rw-r--r--ObjectDLL/GabriellaAI.h50
-rw-r--r--ObjectDLL/GabriellaREV.cpp584
-rw-r--r--ObjectDLL/GabriellaREV.h50
-rw-r--r--ObjectDLL/GameInvItems.cpp1163
-rw-r--r--ObjectDLL/GameInvItems.h208
-rw-r--r--ObjectDLL/GameProjectiles.cpp7178
-rw-r--r--ObjectDLL/GameProjectiles.h892
-rw-r--r--ObjectDLL/GameStartPoint.cpp174
-rw-r--r--ObjectDLL/GameStartPoint.h45
-rw-r--r--ObjectDLL/GameWeapons.cpp2576
-rw-r--r--ObjectDLL/GameWeapons.h768
-rw-r--r--ObjectDLL/Gib.cpp915
-rw-r--r--ObjectDLL/Gib.h118
-rw-r--r--ObjectDLL/Gideon.cpp874
-rw-r--r--ObjectDLL/Gideon.h77
-rw-r--r--ObjectDLL/GooSplat.cpp100
-rw-r--r--ObjectDLL/GooSplat.h39
-rw-r--r--ObjectDLL/Gremlin.cpp657
-rw-r--r--ObjectDLL/Gremlin.h55
-rw-r--r--ObjectDLL/HandWeaponModel.cpp240
-rw-r--r--ObjectDLL/HandWeaponModel.h74
-rw-r--r--ObjectDLL/Impacts.cpp380
-rw-r--r--ObjectDLL/Impacts.h89
-rw-r--r--ObjectDLL/InvItem.cpp44
-rw-r--r--ObjectDLL/InvItem.h231
-rw-r--r--ObjectDLL/InventoryMgr.cpp3088
-rw-r--r--ObjectDLL/InventoryMgr.h474
-rw-r--r--ObjectDLL/IshmaelAI.cpp620
-rw-r--r--ObjectDLL/IshmaelAI.h57
-rw-r--r--ObjectDLL/IshmaelREV.cpp622
-rw-r--r--ObjectDLL/IshmaelREV.h57
-rw-r--r--ObjectDLL/ItemPickups.cpp511
-rw-r--r--ObjectDLL/ItemPickups.h175
-rw-r--r--ObjectDLL/Key.cpp153
-rw-r--r--ObjectDLL/Key.h45
-rw-r--r--ObjectDLL/KeyData.cpp193
-rw-r--r--ObjectDLL/KeyData.h49
-rw-r--r--ObjectDLL/KeyFramer.cpp849
-rw-r--r--ObjectDLL/KeyFramer.h81
-rw-r--r--ObjectDLL/LightFX.cpp1213
-rw-r--r--ObjectDLL/LightFX.h130
-rw-r--r--ObjectDLL/MadScientistAI.cpp272
-rw-r--r--ObjectDLL/MadScientistAI.h46
-rw-r--r--ObjectDLL/ModelObject.cpp265
-rw-r--r--ObjectDLL/ModelObject.h54
-rw-r--r--ObjectDLL/Music.cpp158
-rw-r--r--ObjectDLL/Music.h52
-rw-r--r--ObjectDLL/Naga.cpp692
-rw-r--r--ObjectDLL/Naga.h73
-rw-r--r--ObjectDLL/NagaCeilingDebris.cpp128
-rw-r--r--ObjectDLL/NagaCeilingDebris.h27
-rw-r--r--ObjectDLL/ObjectDLL.dsp1341
-rw-r--r--ObjectDLL/ObjectUtilities.cpp591
-rw-r--r--ObjectDLL/ObjectUtilities.h210
-rw-r--r--ObjectDLL/ObjectivesTrigger.cpp247
-rw-r--r--ObjectDLL/ObjectivesTrigger.h42
-rw-r--r--ObjectDLL/OpheliaAI.cpp602
-rw-r--r--ObjectDLL/OpheliaAI.h50
-rw-r--r--ObjectDLL/OpheliaREV.cpp608
-rw-r--r--ObjectDLL/OpheliaREV.h50
-rw-r--r--ObjectDLL/ParticleSystem.cpp224
-rw-r--r--ObjectDLL/ParticleSystem.h51
-rw-r--r--ObjectDLL/PathList.h203
-rw-r--r--ObjectDLL/PathListData.cpp114
-rw-r--r--ObjectDLL/PathListData.h36
-rw-r--r--ObjectDLL/PathMgr.cpp182
-rw-r--r--ObjectDLL/PathMgr.h51
-rw-r--r--ObjectDLL/PhysicalAttributes.h34
-rw-r--r--ObjectDLL/PickupObject.cpp674
-rw-r--r--ObjectDLL/PickupObject.h111
-rw-r--r--ObjectDLL/PlayerObj.cpp7657
-rw-r--r--ObjectDLL/PlayerObj.h502
-rw-r--r--ObjectDLL/PolyGrid.cpp302
-rw-r--r--ObjectDLL/PolyGrid.h61
-rw-r--r--ObjectDLL/PowerupPickups.cpp375
-rw-r--r--ObjectDLL/PowerupPickups.h117
-rw-r--r--ObjectDLL/Projectile.cpp926
-rw-r--r--ObjectDLL/Projectile.h125
-rw-r--r--ObjectDLL/Rain.cpp347
-rw-r--r--ObjectDLL/Rain.h56
-rw-r--r--ObjectDLL/RandomSoundFX.cpp542
-rw-r--r--ObjectDLL/RandomSoundFX.h71
-rw-r--r--ObjectDLL/RatAI.cpp189
-rw-r--r--ObjectDLL/RatAI.h50
-rw-r--r--ObjectDLL/Rotating.cpp750
-rw-r--r--ObjectDLL/Rotating.h101
-rw-r--r--ObjectDLL/RotatingBrush.cpp78
-rw-r--r--ObjectDLL/RotatingBrush.h35
-rw-r--r--ObjectDLL/RotatingDoor.cpp525
-rw-r--r--ObjectDLL/RotatingDoor.h59
-rw-r--r--ObjectDLL/RotatingModel.cpp76
-rw-r--r--ObjectDLL/RotatingModel.h35
-rw-r--r--ObjectDLL/RotatingSprite.cpp58
-rw-r--r--ObjectDLL/RotatingSprite.h31
-rw-r--r--ObjectDLL/Script.cpp3562
-rw-r--r--ObjectDLL/Script.h165
-rw-r--r--ObjectDLL/ScriptList.h287
-rw-r--r--ObjectDLL/SeeingEye.cpp516
-rw-r--r--ObjectDLL/SeeingEye.h58
-rw-r--r--ObjectDLL/ShellCasing.cpp420
-rw-r--r--ObjectDLL/ShellCasing.h58
-rw-r--r--ObjectDLL/ShikariAI.cpp671
-rw-r--r--ObjectDLL/ShikariAI.h55
-rw-r--r--ObjectDLL/SmellHint.cpp74
-rw-r--r--ObjectDLL/SmellHint.h48
-rw-r--r--ObjectDLL/SoccerObjects.cpp931
-rw-r--r--ObjectDLL/SoccerObjects.h124
-rw-r--r--ObjectDLL/SoulDrudge.cpp404
-rw-r--r--ObjectDLL/SoulDrudge.h48
-rw-r--r--ObjectDLL/SoundFX.cpp609
-rw-r--r--ObjectDLL/SoundFX.h72
-rw-r--r--ObjectDLL/Sparam.cpp131
-rw-r--r--ObjectDLL/Sparam.h35
-rw-r--r--ObjectDLL/SparksObj.cpp403
-rw-r--r--ObjectDLL/SparksObj.h82
-rw-r--r--ObjectDLL/Spawner.cpp477
-rw-r--r--ObjectDLL/Spawner.h54
-rw-r--r--ObjectDLL/SpellPickups.cpp117
-rw-r--r--ObjectDLL/SpellPickups.h47
-rw-r--r--ObjectDLL/Tchernotronic.cpp483
-rw-r--r--ObjectDLL/Tchernotronic.h51
-rw-r--r--ObjectDLL/TheHandAI.cpp551
-rw-r--r--ObjectDLL/TheHandAI.h58
-rw-r--r--ObjectDLL/Trigger.cpp1341
-rw-r--r--ObjectDLL/Trigger.h161
-rw-r--r--ObjectDLL/TripLaser.cpp567
-rw-r--r--ObjectDLL/TripLaser.h60
-rw-r--r--ObjectDLL/UndeadGideon.cpp716
-rw-r--r--ObjectDLL/UndeadGideon.h64
-rw-r--r--ObjectDLL/ViewWeaponModel.cpp183
-rw-r--r--ObjectDLL/ViewWeaponModel.h95
-rw-r--r--ObjectDLL/VoiceMgr.cpp888
-rw-r--r--ObjectDLL/VoiceMgr.h216
-rw-r--r--ObjectDLL/VolumeBrush.cpp880
-rw-r--r--ObjectDLL/VolumeBrush.h101
-rw-r--r--ObjectDLL/VolumeBrushTypes.cpp538
-rw-r--r--ObjectDLL/VolumeBrushTypes.h111
-rw-r--r--ObjectDLL/Weapon.cpp2084
-rw-r--r--ObjectDLL/Weapon.h231
-rw-r--r--ObjectDLL/WeaponPickups.cpp558
-rw-r--r--ObjectDLL/WeaponPickups.h173
-rw-r--r--ObjectDLL/WorldModelDebris.cpp237
-rw-r--r--ObjectDLL/WorldModelDebris.h45
-rw-r--r--ObjectDLL/WorldProperties.cpp378
-rw-r--r--ObjectDLL/WreckingBall.cpp379
-rw-r--r--ObjectDLL/WreckingBall.h45
-rw-r--r--ObjectDLL/ZealotAI.cpp950
-rw-r--r--ObjectDLL/ZealotAI.h74
-rw-r--r--ObjectDLL/behemoth.cpp418
-rw-r--r--ObjectDLL/behemoth.h47
-rw-r--r--ObjectDLL/behemoth_logic.h66
-rw-r--r--ObjectDLL/bird_logic.h66
-rw-r--r--ObjectDLL/boneleech.cpp563
-rw-r--r--ObjectDLL/boneleech.h58
-rw-r--r--ObjectDLL/bug.cpp330
-rw-r--r--ObjectDLL/bug.h52
-rw-r--r--ObjectDLL/bug_logic.h66
-rw-r--r--ObjectDLL/civilian_logic.h66
-rw-r--r--ObjectDLL/clientbloodtrail.cpp159
-rw-r--r--ObjectDLL/clientbloodtrail.h36
-rw-r--r--ObjectDLL/clientdebugline.cpp81
-rw-r--r--ObjectDLL/clientdebugline.h30
-rw-r--r--ObjectDLL/corpse.cpp894
-rw-r--r--ObjectDLL/corpse.h105
-rw-r--r--ObjectDLL/cultist_logic.h66
-rw-r--r--ObjectDLL/drudgelord_logic.h66
-rw-r--r--ObjectDLL/drudgepriest.cpp533
-rw-r--r--ObjectDLL/drudgepriest.h64
-rw-r--r--ObjectDLL/fanatic_logic.h66
-rw-r--r--ObjectDLL/gremlin_logic.h66
-rw-r--r--ObjectDLL/madscientist_logic.h66
-rw-r--r--ObjectDLL/movement.cpp638
-rw-r--r--ObjectDLL/movement.h115
-rw-r--r--ObjectDLL/nightmare.cpp501
-rw-r--r--ObjectDLL/nightmare.h65
-rw-r--r--ObjectDLL/pathpoint.cpp248
-rw-r--r--ObjectDLL/pathpoint.h51
-rw-r--r--ObjectDLL/prophet.cpp634
-rw-r--r--ObjectDLL/prophet.h52
-rw-r--r--ObjectDLL/prophet_logic.h66
-rw-r--r--ObjectDLL/rat_logic.h66
-rw-r--r--ObjectDLL/shikari_logic.h66
-rw-r--r--ObjectDLL/souldrudge_logic.h66
-rw-r--r--ObjectDLL/thehand_logic.h66
-rw-r--r--ObjectDLL/thief.cpp549
-rw-r--r--ObjectDLL/thief.h58
-rw-r--r--ObjectDLL/wurmAI.cpp466
-rw-r--r--ObjectDLL/wurmAI.h63
-rw-r--r--ObjectDLL/zealot_logic.h66
-rw-r--r--Readme.txt120
-rw-r--r--Shared/ClientRes.h917
-rw-r--r--Shared/ClientServerShared.h119
-rw-r--r--Shared/Commands.h63
-rw-r--r--Shared/ContainerCodes.h64
-rw-r--r--Shared/DynArray.h93
-rw-r--r--Shared/NetDefs.h163
-rw-r--r--Shared/SFXMsgIds.h272
-rw-r--r--Shared/SharedDefs.h654
-rw-r--r--Shared/SharedMovement.h53
-rw-r--r--Shared/SoundTypes.h32
-rw-r--r--Shared/TeamMgr.cpp1399
-rw-r--r--Shared/TeamMgr.h427
-rw-r--r--Shared/VoiceMgrDefs.h74
-rw-r--r--Shared/WeaponDefs.cpp3279
-rw-r--r--Shared/WeaponDefs.h142
-rw-r--r--softdib.renbin0 -> 266240 bytes
627 files changed, 224688 insertions, 0 deletions
diff --git a/AppHeaders/CSBase.h b/AppHeaders/CSBase.h
new file mode 100644
index 0000000..7e871f4
--- /dev/null
+++ b/AppHeaders/CSBase.h
@@ -0,0 +1,97 @@
+
+// Base class for ClientDE and ServerDE. This is just here for b/w compatibility.
+
+#ifndef __CSBASE_H__
+#define __CSBASE_H__
+
+
+ #include "basedefs_de.h"
+
+
+ class CSBase
+ {
+ // Messaging functions. ALL these functions are obsolete. Use the LMessage functions.
+ public:
+
+ // Start a data message for writing. A data message is used to write an HMESSAGEWRITE into another
+ // already open HMESSAGEWRITE. When the data message is complete, first call
+ // WriteToMessageHMessageWrite to write it into the other HMESSAGE, then call EndMessageHMessageWrite to free it.
+ virtual HMESSAGEWRITE StartHMessageWrite()=0;
+
+ virtual DRESULT WriteToMessageFloat(HMESSAGEWRITE hMessage, float val);
+ virtual DRESULT WriteToMessageByte(HMESSAGEWRITE hMessage, DBYTE val);
+ virtual DRESULT WriteToMessageWord(HMESSAGEWRITE hMessage, D_WORD val);
+ virtual DRESULT WriteToMessageDWord(HMESSAGEWRITE hMessage, DDWORD val);
+ virtual DRESULT WriteToMessageString(HMESSAGEWRITE hMessage, char *pStr);
+ virtual DRESULT WriteToMessageVector(HMESSAGEWRITE hMessage, DVector *pVal); // 12 bytes
+ virtual DRESULT WriteToMessageCompVector(HMESSAGEWRITE hMessage, DVector *pVal); // 9 bytes
+ virtual DRESULT WriteToMessageCompPosition(HMESSAGEWRITE hMessage, DVector *pVal); // 7 bytes
+ virtual DRESULT WriteToMessageRotation(HMESSAGEWRITE hMessage, DRotation *pVal);
+ virtual DRESULT WriteToMessageHString(HMESSAGEWRITE hMessage, HSTRING hString);
+
+ // Writes a HMESSAGEWRITE into an already opened HMESSAGEWRITE.
+ // Inputs:
+ // hMessage - HMESSAGEWRITE written to.
+ // hDataMessage - HMESSAGEWRITE written from.
+ virtual DRESULT WriteToMessageHMessageWrite(HMESSAGEWRITE hMessage, HMESSAGEWRITE hDataMessage);
+
+ // Writes a HMESSAGEREAD into an already opened HMESSAGEWRITE.
+ // Inputs:
+ // hMessage - HMESSAGEWRITE written to.
+ // hDataMessage - HMESSAGEREAD written from.
+ virtual DRESULT WriteToMessageHMessageRead(HMESSAGEWRITE hMessage, HMESSAGEREAD hDataMessage);
+
+ // Helper so you don't have to FormatString and FreeString..
+ virtual DRESULT WriteToMessageFormattedHString(HMESSAGEWRITE hMessage, int messageCode, ...);
+
+ // Note: you can't send object references to the client yet, so the client can't
+ // even read object references.
+ // You can't write object references in a HMESSAGEWRITE passed in MID_SAVEOBJECT.
+ virtual DRESULT WriteToMessageObject(HMESSAGEWRITE hMessage, HOBJECT hObj);
+
+ // Use this only while saving objects (inside MID_SAVEOBJECT).
+ virtual DRESULT WriteToLoadSaveMessageObject(HMESSAGEWRITE hMessage, HOBJECT hObject);
+
+
+ // When your OnMessage function is called, use the handle you're given
+ // to read the message data with these functions.
+ virtual float ReadFromMessageFloat(HMESSAGEREAD hMessage);
+ virtual DBYTE ReadFromMessageByte(HMESSAGEREAD hMessage);
+ virtual D_WORD ReadFromMessageWord(HMESSAGEREAD hMessage);
+ virtual DDWORD ReadFromMessageDWord(HMESSAGEREAD hMessage);
+ virtual char* ReadFromMessageString(HMESSAGEREAD hMessage);
+ virtual void ReadFromMessageVector(HMESSAGEREAD hMessage, DVector *pVal); // 12 bytes
+ virtual void ReadFromMessageCompVector(HMESSAGEREAD hMessage, DVector *pVal); // 9 bytes
+ virtual void ReadFromMessageCompPosition(HMESSAGEREAD hMessage, DVector *pVal); // 7 bytes
+ virtual void ReadFromMessageRotation(HMESSAGEREAD hMessage, DRotation *pVal);
+ virtual HOBJECT ReadFromMessageObject(HMESSAGEREAD hMessage);
+ virtual HSTRING ReadFromMessageHString(HMESSAGEREAD hMessage);
+
+ // Use this only while loading objects (inside MID_LOADOBJECT).
+ virtual DRESULT ReadFromLoadSaveMessageObject(HMESSAGEREAD hMessage, HOBJECT *hObject);
+
+ // Reads a data message from an HMESSAGEREAD. The returned HMESSAGEREAD can then be used in the
+ // ReadFromMessageX functions. This will create a new HMESSAGEREAD which must be
+ // freed with a call to EndHMessageRead().
+ // Inputs:
+ // hMessage - HMESSAGEREAD read from.
+ virtual HMESSAGEREAD ReadFromMessageHMessageRead(HMESSAGEREAD hMessage);
+
+ // Frees a HMESSAGEREAD created from a call of ReadFromMessageHMessageRead.
+ virtual void EndHMessageRead(HMESSAGEREAD hMessage);
+
+ // Frees a HMESSAGEWRITE created from a call of StartHMessageWrite.
+ virtual void EndHMessageWrite(HMESSAGEWRITE hMessage);
+
+ // Reset reading (so you can read the message again).
+ // This is useful if you read out of a message and subclasses
+ // will be reading out of it. Note: the message will AUTOMATICALLY
+ // reset when you hit the end, so you won't need this in most cases.
+ virtual void ResetRead(HMESSAGEREAD hRead);
+ };
+
+
+#endif
+
+
+
diff --git a/AppHeaders/DVector.h b/AppHeaders/DVector.h
new file mode 100644
index 0000000..a8d84cc
--- /dev/null
+++ b/AppHeaders/DVector.h
@@ -0,0 +1,372 @@
+
+#ifndef __DVECTOR_H__
+#define __DVECTOR_H__
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ //
+ // C++ Vector Class
+ //
+ //
+
+
+ // Don't worry about all the template stuff, just always use this.
+ #define DVector _CVector<float>
+
+
+ // Defines....
+ #define ZERO 0.0f
+ #define ONE 1.0f
+ #define DIFF(x,y) ( (x)<(y) ? ((y)-(x)) : ((x)-(y)) )
+ #define ABS(x) ( (x)<0 ? (-(x)) : (x) )
+
+
+ template<class T>
+ class _CVector
+ {
+ public:
+
+
+ _CVector() {}
+ _CVector(T mx, T my, T mz) {x=mx; y=my; z=mz;}
+
+ // Member Functions
+ void Init(T px=0.0f, T py=0.0f, T pz=0.0f) { x = px; y = py; z = pz; }
+ void Term();
+
+ T Mag() const { return (T)sqrt((x * x) + (y * y) + (z * z)); }
+ T MagSqr() const { return (x * x) + (y * y) + (z * z); }
+ T MagApprox() const;
+
+ T Dot(_CVector<T> v) const { return (x * v.x) + (y * v.y) + (z * v.z); }
+
+ void Norm(T nVal = ONE);
+ void NormApprox(T nVal = ONE);
+ _CVector<T> Cross( _CVector<T> v ) const;
+
+ _CVector<float> FVec() {return _CVector<float>((float)x, (float)y, (float)z);}
+ _CVector<double> DVec() {return _CVector<double>((double)x, (double)y, (double)z);}
+
+ DBOOL Equals( _CVector<T> &v, T variance=ZERO ) const;
+
+ // Operators
+ _CVector<T> operator - () const { return _CVector<T>(-x, -y, -z); }
+
+ _CVector<T> operator + (_CVector<T> v) const { return _CVector<T>(x + v.x, y + v.y, z + v.z); }
+ _CVector<T> operator - (_CVector<T> v) const { return _CVector<T>(x - v.x, y - v.y, z - v.z); }
+ _CVector<T> operator * (_CVector<T> v) const { return _CVector<T>(x * v.x, y * v.y, z * v.z); }
+ _CVector<T> operator / (_CVector<T> v) const { return _CVector<T>(x / v.x, y / v.y, z / v.z); }
+
+ _CVector<T> operator + (T v) const { return _CVector<T>(x + v, y + v, z + v); }
+ _CVector<T> operator - (T v) const { return _CVector<T>(x - v, y - v, z - v); }
+ _CVector<T> operator * (T v) const { return _CVector<T>(x * v, y * v, z * v); }
+ _CVector<T> operator / (T v) const { return _CVector<T>(x / v, y / v, z / v); }
+
+ _CVector<T> Inverse() const
+ {
+ _CVector<T> temp;
+ temp = *this;
+ temp.Norm();
+ temp *= 1.0f / Mag();
+ return temp;
+ }
+
+ void operator += (_CVector<T> v) { x += v.x; y += v.y; z += v.z; }
+ void operator -= (_CVector<T> v) { x -= v.x; y -= v.y; z -= v.z; }
+ void operator *= (_CVector<T> v) { x *= v.x; y *= v.y; z *= v.z; }
+ void operator /= (_CVector<T> v) { x /= v.x; y /= v.y; z /= v.z; }
+
+ void operator += (T v) { x += v; y += v; z += v; }
+ void operator -= (T v) { x -= v; y -= v; z -= v; }
+ void operator *= (T v) { x *= v; y *= v; z *= v; }
+ void operator /= (T v) { x /= v; y /= v; z /= v; }
+
+ DBOOL operator > ( _CVector<T> &other ) { return ((x>other.x) && (y>other.y) && (z>other.z)); }
+ DBOOL operator < ( _CVector<T> &other ) { return ((x<other.x) && (y<other.y) && (z<other.z)); }
+
+ DBOOL operator >= ( _CVector<T> &other ) { return ((x>=other.x) && (y>=other.y) && (z>=other.z)); }
+ DBOOL operator <= ( _CVector<T> &other ) { return ((x<=other.x) && (y<=other.y) && (z<=other.z)); }
+
+ DBOOL operator == ( _CVector<T> &other ) { return ((x==other.x) && (y==other.y) && (z==other.z)); }
+ DBOOL operator != ( _CVector<T> &other ) { return ((x!=other.x) || (y!=other.y) || (z!=other.z)); }
+
+ _CVector<T> operator ^ ( _CVector<T> v ) const { return Cross(v); }
+ T &operator [] ( DDWORD i ) { return ((T*)this)[i]; }
+
+ // Member Variables
+ T x;
+ T y;
+ T z;
+
+ };
+
+
+
+
+ //------------------------------------------------------------------
+ //
+ // Function : CVector::Equals
+ //
+ // Purpose : Returns if two vectors are equal (it sees if the
+ // difference between each coordinate is less than
+ // variance)
+ //
+ //------------------------------------------------------------------
+
+ template<class T>
+ inline DBOOL _CVector<T>::Equals( _CVector<T> &v, T variance ) const
+ {
+ return ((DIFF(x,v.x)<=variance) && (DIFF(y,v.y)<=variance) && (DIFF(z,v.z)<=variance));
+ }
+
+
+
+ //------------------------------------------------------------------
+ //
+ // Function : MagApprox
+ //
+ // Purpose : Approximate magnitude of vector (within 12%)
+ //
+ //------------------------------------------------------------------
+
+ template<class T>
+ inline T _CVector<T>::MagApprox () const
+ {
+ T min, med, max;
+ T temp;
+
+ max = ABS( x );
+ med = ABS( y );
+ min = ABS( z );
+
+ if( max < med )
+ {
+ temp = max;
+ max = med;
+ med = temp;
+ }
+
+ if( max < min )
+ {
+ temp = max;
+ max = min;
+ min = temp;
+ }
+
+ return max + ((med + min) * 0.25f);
+ }
+
+
+
+ //------------------------------------------------------------------
+ //
+ // Function : Norm
+ //
+ // Purpose : Normalises a vector
+ //
+ //------------------------------------------------------------------
+
+ template<class T>
+ inline void _CVector<T>::Norm( T nVal )
+ {
+ T inv;
+ T mag = Mag();
+
+ if (mag == 0.0f)
+ return;
+
+ inv = nVal / mag;
+ x = x * inv;
+ y = y * inv;
+ z = z * inv;
+ }
+
+
+
+ //------------------------------------------------------------------
+ //
+ // Function : NormApprox
+ //
+ // Purpose : Normalises a vector using an approximation to the
+ // magnitude.
+ //
+ //------------------------------------------------------------------
+
+ template<class T>
+ inline void _CVector<T>::NormApprox( T nVal )
+ {
+ T inv;
+ T mag = MagApprox();
+
+ if (mag == 0.0f)
+ return;
+
+ inv = nVal / mag;
+ x = x * inv;
+ y = y * inv;
+ z = z * inv;
+ }
+
+
+
+ //------------------------------------------------------------------
+ //
+ // Function : Cross
+ //
+ // Purpose : Calculates cross product of vector
+ //
+ //------------------------------------------------------------------
+
+ template<class T>
+ inline _CVector<T> _CVector<T>::Cross ( _CVector<T> v ) const
+ {
+ return _CVector<T>(
+ ((v.y * z) - (v.z * y)),
+ ((v.z * x) - (v.x * z)),
+ ((v.x * y) - (v.y * x))
+ );
+ }
+
+
+ // Vector macros.
+
+ // MAKE SURE NOT TO HAVE DEST BE SOURCE1 OR SOURCE2 or it'll screw up!
+ #define VEC_CROSS(dest, v1, v2) \
+ {\
+ (dest).x = ((v2).y*(v1).z - (v2).z*(v1).y);\
+ (dest).y = ((v2).z*(v1).x - (v2).x*(v1).z);\
+ (dest).z = ((v2).x*(v1).y - (v2).y*(v1).x);\
+ }
+
+
+ #define VEC_ADD(d, v1, v2) \
+ {\
+ (d).x = (v1).x + (v2).x;\
+ (d).y = (v1).y + (v2).y;\
+ (d).z = (v1).z + (v2).z;\
+ }
+
+ #define VEC_ADDSCALED(d, v1, v2, s) \
+ {\
+ (d).x = (v1).x + ((v2).x * (s));\
+ (d).y = (v1).y + ((v2).y * (s));\
+ (d).z = (v1).z + ((v2).z * (s));\
+ }
+
+ #define VEC_SUB(d, v1, v2) \
+ {\
+ (d).x = (v1).x - (v2).x;\
+ (d).y = (v1).y - (v2).y;\
+ (d).z = (v1).z - (v2).z;\
+ }
+
+ #define VEC_MUL(d, v1, v2) \
+ {\
+ (d).x = (v1).x * (v2).x;\
+ (d).y = (v1).y * (v2).y;\
+ (d).z = (v1).z * (v2).z;\
+ }
+
+ #define VEC_DIV(d, v1, v2) \
+ {\
+ (d).x = (v1).x / (v2).x;\
+ (d).y = (v1).y / (v2).y;\
+ (d).z = (v1).z / (v2).z;\
+ }
+
+ #define VEC_MULSCALAR(d, v1, s) \
+ {\
+ (d).x = (v1).x * (s); \
+ (d).y = (v1).y * (s); \
+ (d).z = (v1).z * (s); \
+ }
+
+ #define VEC_DIVSCALAR(d, v1, s) \
+ {\
+ (d).x = (v1).x / (s); \
+ (d).y = (v1).y / (s); \
+ (d).z = (v1).z / (s);\
+ }
+
+ #define VEC_LERP(d, v1, v2, t) \
+ {\
+ (d).x = (v1).x + ((v2).x - (v1).x) * t;\
+ (d).y = (v1).y + ((v2).y - (v1).y) * t;\
+ (d).z = (v1).z + ((v2).z - (v1).z) * t;\
+ }
+
+ #define VEC_CLAMP(v, a, b) \
+ {\
+ (v).x = DCLAMP((v).x, a, b);\
+ (v).y = DCLAMP((v).y, a, b);\
+ (v).z = DCLAMP((v).z, a, b);\
+ }
+
+ #define VEC_MIN(v, a, b) \
+ {\
+ (v).x = DMIN((a).x, (b).x);\
+ (v).y = DMIN((a).y, (b).y);\
+ (v).z = DMIN((a).z, (b).z);\
+ }
+
+ #define VEC_MAX(v, a, b) \
+ {\
+ (v).x = DMAX((a).x, (b).x);\
+ (v).y = DMAX((a).y, (b).y);\
+ (v).z = DMAX((a).z, (b).z);\
+ }
+
+ #define VEC_NEGATE(d, s) \
+ {\
+ (d).x = -(s).x; \
+ (d).y = -(s).y; \
+ (d).z = -(s).z; \
+ }
+
+ // Dot product of 2 vectors.
+ #define VEC_DOT(v1, v2) ( (v1).x*(v2).x + (v1).y*(v2).y + (v1).z*(v2).z )
+
+ // Expand the vector for function calls..
+ #define EXPANDVEC(vec) (vec).x, (vec).y, (vec).z
+
+ // Distance between 2 vectors.
+ #define VEC_DISTSQR(v1, v2) ( \
+ ((v1).x-(v2).x) * ((v1).x-(v2).x) + \
+ ((v1).y-(v2).y) * ((v1).y-(v2).y) + \
+ ((v1).z-(v2).z) * ((v1).z-(v2).z) )
+
+ #define VEC_DIST(v1, v2) ((float)sqrt(VEC_DISTSQR(v1, v2)))
+
+ #define VEC_MAGSQR(v) ((v).x*(v).x + (v).y*(v).y + (v).z*(v).z)
+ #define VEC_MAG(v) ((float)sqrt(VEC_MAGSQR(v)))
+
+ #define VEC_INVMAG(v) (1.0f / VEC_MAG(v))
+
+ #define VEC_NORM(v) \
+ {\
+ float __temp_normalizer_____;\
+ __temp_normalizer_____ = 1.0f / VEC_MAG(v);\
+ (v).x *= __temp_normalizer_____;\
+ (v).y *= __temp_normalizer_____;\
+ (v).z *= __temp_normalizer_____;\
+ }
+
+ #define VEC_COPY(dest, src) \
+ {\
+ (dest).x = (src).x; (dest).y = (src).y; (dest).z = (src).z;\
+ }
+
+ #define VEC_SET(v, vx, vy, vz) \
+ {\
+ (v).x = (float)(vx); (v).y = (float)(vy); (v).z = (float)(vz);\
+ }
+
+ #define VEC_EXPAND(v) (v).x, (v).y, (v).z
+ #define VEC_INIT(v) (v).x = (v).y = (v).z = 0.0f;
+ #define VEC_INDEX(v, i) (((float*)&(v))[i])
+
+
+#endif
+
+
+
diff --git a/AppHeaders/SpriteControl.h b/AppHeaders/SpriteControl.h
new file mode 100644
index 0000000..e4f1e8c
--- /dev/null
+++ b/AppHeaders/SpriteControl.h
@@ -0,0 +1,30 @@
+
+#ifndef __SPRITECONTROL_H__
+#define __SPRITECONTROL_H__
+
+
+ // Sprite control flags. Default flags for a sprite are SC_PLAY|SC_LOOP.
+ #define SC_PLAY (1<<0)
+ #define SC_LOOP (1<<1)
+
+
+ class SpriteControl
+ {
+ public:
+
+ virtual DRESULT GetNumAnims(DDWORD &nAnims)=0;
+ virtual DRESULT GetNumFrames(DDWORD iAnim, DDWORD &nFrames)=0;
+
+ virtual DRESULT GetCurPos(DDWORD &iAnim, DDWORD &iFrame)=0;
+ virtual DRESULT SetCurPos(DDWORD iAnim, DDWORD iFrame)=0;
+
+ virtual DRESULT GetFlags(DDWORD &flags)=0;
+ virtual DRESULT SetFlags(DDWORD flags)=0;
+ };
+
+
+#endif
+
+
+
+
diff --git a/AppHeaders/aggregate_de.h b/AppHeaders/aggregate_de.h
new file mode 100644
index 0000000..2ed2434
--- /dev/null
+++ b/AppHeaders/aggregate_de.h
@@ -0,0 +1,36 @@
+
+// This header file defines the base aggregate structure. Every
+// aggregate must have a link to its next one and a pointer
+// to certain functions that an aggregate must supply.
+// When implementing an aggregate, you MUST derive from this!
+// (In C, just put it as the first member in your structure..)
+
+#ifndef __AGGREGATE_DE__
+#define __AGGREGATE_DE__
+
+#include "basedefs_de.h"
+
+ typedef DDWORD (*AggregateEngineMessageFn)(LPBASECLASS pObject, LPAGGREGATE pAggregate,
+ DDWORD messageID, void *pData, float fData);
+
+ typedef DDWORD (*AggregateObjectMessageFn)(LPBASECLASS pObject, LPAGGREGATE pAggregate,
+ HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+
+
+ #ifdef COMPILE_WITH_C
+ typedef struct Aggregate_t
+ {
+ // This is so DirectEngine will skip over a C++ object's VTable.
+ void *cpp_4BytesForVTable;
+
+ struct Aggregate_t *m_pNextAggregate;
+
+ // Hook functions for the aggregate..
+ AggregateEngineMessageFn m_EngineMessageFn;
+ AggregateObjectMessageFn m_ObjectMessageFn;
+
+ } Aggregate;
+ #endif
+
+
+#endif // __AGGREGATE_DE__
diff --git a/AppHeaders/basedefs_de.h b/AppHeaders/basedefs_de.h
new file mode 100644
index 0000000..0c1f95a
--- /dev/null
+++ b/AppHeaders/basedefs_de.h
@@ -0,0 +1,849 @@
+
+#ifndef __BASEDEFS_H__
+#define __BASEDEFS_H__
+
+
+ #include <stdlib.h>
+ #include <string.h>
+
+ #ifdef __cplusplus
+ #define BEGIN_EXTERNC() extern "C" \
+ {
+ #define END_EXTERNC() };
+ #else
+ #define BEGIN_EXTERNC()
+ #define END_EXTERNC()
+ #endif
+
+
+ #if !defined(__cplusplus) || defined(DIRECTENGINE_COMPILE)
+ #define COMPILE_WITH_C
+ #endif
+
+ #ifdef COMPILE_WITH_C
+ #define LPBASECLASS struct BaseClass_t *
+ #define LPAGGREGATE struct Aggregate_t *
+ #else
+ class BaseClass;
+ #define LPBASECLASS BaseClass*
+ class Aggregate;
+ #define LPAGGREGATE Aggregate*
+ #endif
+
+
+ // Useful...
+ #define SAFE_STRCPY(dest, src) \
+ {\
+ if(sizeof(dest) > 4)\
+ {\
+ strncpy(dest, src, sizeof(dest)-1);\
+ dest[sizeof(dest)-1] = 0; \
+ }\
+ else\
+ {\
+ strcpy(dest, src);\
+ }\
+ }
+
+
+ // Used in GetFileList/FreeFileList.
+ #define TYPE_FILE 1
+ #define TYPE_DIRECTORY 2
+
+ typedef struct FileEntry_t
+ {
+ int m_Type; // Directory or file?
+ char *m_pBaseFilename; // pic1.pcx
+ char *m_pFullFilename; // interface/bitmaps/pic1.pcx
+ struct FileEntry_t *m_pNext;
+ } FileEntry;
+
+
+ // Used in the counter functions.
+ typedef struct DCounter_t
+ {
+ unsigned long m_Data[4];
+ } DCounter;
+
+
+
+ #define DEFINE_HANDLE_TYPE(name) \
+ typedef struct {int __nothing;} ##name##_t, *name;
+
+
+ #define MAX_CS_FILENAME_LEN 100
+
+ // HMESSAGE defines
+
+ // Maximum number of bytes in a grouped of messages of a communications message.
+ #define MAX_PACKET_LEN 1024
+
+ // Maxumum number of bytes in a message of a communications message.
+ #define MAX_MESSAGE_LEN 1024
+
+ // Maximum number of bytes a single object can save into MID_SAVEOBJECT message.
+ #define MAX_SAVEOBJECT_LEN 8192
+
+
+ // Model state flags.
+ #define MS_PLAYDONE 1 // The (nonlooping) model has finished playing the animation.
+
+
+ // HDECOLOR stuff.
+ typedef unsigned long HDECOLOR;
+ #define COLOR_TRANSPARENCY_MASK 0x80000000
+
+ // r, g, and b, are 0-255 integers.
+ #define SETRGB(r,g,b) \
+ (((unsigned long)(r) << 16) | ((unsigned long)(g) << 8) | ((unsigned long)(b)))
+
+ // r, g, and b are 0-1 floats.
+ #define SETRGB_F(r,g,b) \
+ (((unsigned long)((r)*255.0f) << 16) | ((unsigned long)((g)*255.0f) << 8) | ((unsigned long)((b)*255.0f)))
+
+ // Setup a color with transparency.
+ #define SETRGB_T(r,g,b) (SETRGB((r),(g),(b)) | COLOR_TRANSPARENCY_MASK)
+ #define SETRGB_FT(r,g,b) (SETRGB_F((r),(g),(b)) | COLOR_TRANSPARENCY_MASK)
+
+ // Gets r, g, and b as 0-255 integers.
+ #define GETR(val) (((val) >> 16) & 0xFF)
+ #define GETG(val) (((val) >> 8) & 0xFF)
+ #define GETB(val) ((val) & 0xFF)
+ #define GETRGB(val, r, g, b) \
+ {\
+ (r) = GETR(val);\
+ (g) = GETG(val);\
+ (b) = GETB(val);\
+ }
+
+ // Gets translucency value (into a 0 or 1 integer).
+ #define GETT(val) (!!((val) & COLOR_TRANSPARENCY_MASK))
+
+
+ class LMessage;
+ typedef LMessage* HMESSAGEREAD;
+ typedef LMessage* HMESSAGEWRITE;
+
+
+
+ // Handle definitions.. it defines them in this wierd way so
+ // you can't accidentally cast between them.
+ DEFINE_HANDLE_TYPE(HCLASS)
+ DEFINE_HANDLE_TYPE(HSURFACE)
+ DEFINE_HANDLE_TYPE(HDEFONT)
+ DEFINE_HANDLE_TYPE(HSTRING)
+ DEFINE_HANDLE_TYPE(HSOUNDDE)
+ DEFINE_HANDLE_TYPE(HCLIENT);
+ DEFINE_HANDLE_TYPE(HATTACHMENT);
+ DEFINE_HANDLE_TYPE(HNETSERVICE);
+ DEFINE_HANDLE_TYPE(HCONSOLEVAR);
+
+
+ typedef unsigned long HMODELNODE;
+ #define INVALID_MODEL_NODE ((HMODELNODE)-1)
+
+ // Object handle definition.
+ class DObject;
+ typedef DObject* HOBJECT;
+ typedef DObject* HLOCALOBJ;
+
+
+
+
+ // ---------------------------------------------------------------- //
+ // Here is the layout of all message IDs.
+ // ---------------------------------------------------------------- //
+
+ // Server->Client (0-255):
+ // DirectEngine reserves 0-15 and defines:
+ #define STC_BPRINT 0 // Used for debugging.. print a message in the console.
+
+ // Client->Server (0-255):
+ // DirectEngine reserves 0-15.
+
+ // Object->Object (0-65k)
+ // 0-1000 reserved.
+ // 1000-2000 shared general messages (damage, I see you, etc..)
+ // 2000-2500 Riot
+ // 3500-4000 Blood 2
+ // 4000-4500 Dreadon
+
+
+ // This is used all over to classify which side of a polygon something's on.
+ typedef enum
+ {
+ BackSide=0,
+ FrontSide=1,
+ Intersect=2
+ } PolySide;
+
+
+
+ // Include really base stuff.
+ #include "basetypes_de.h"
+ #include "de_codes.h"
+
+
+
+ #define MAX_FORCEUPDATE_OBJECTS 200
+ typedef struct
+ {
+ HOBJECT *m_Objects; // This array is MAX_FORCEUPDATE_OBJECTS large.
+ DDWORD m_nObjects;
+ } ForceUpdate;
+
+
+
+ // This structure is used when creating objects. When you want to
+ // create an object, you call ServerDE::CreateObject with one of these.
+ // The structure you pass in is passed to the object's PostPropRead function,
+ // where it can override whatever it wants to.
+ typedef struct ObjectCreateStruct_t
+ {
+ // Main info.
+ unsigned short m_ObjectType;
+ DDWORD m_Flags;
+ DVector m_Pos;
+ DVector m_Scale;
+ DRotation m_Rotation;
+ D_WORD m_ContainerCode; // Container code if it's a container. It's in here because
+ // you can only set it at creation time.
+
+ DDWORD m_UserData; // User data
+
+
+ char m_Filename[MAX_CS_FILENAME_LEN+1]; // This is the model, sound, or sprite filename.
+ // It also can be the WorldModel name.
+ // This can be zero-length when it's not needed.
+
+ char m_SkinName[MAX_CS_FILENAME_LEN+1]; // This can be zero-length.. if you set it for an
+ // OT_MODEL, it's the skin filename.
+
+ // Server only info.
+ char m_Name[MAX_CS_FILENAME_LEN+1]; // This object's name.
+ float m_NextUpdate; // This will be the object's starting NextUpdate.
+ float m_fDeactivationTime; // Amount of time before object deactivates self
+ } ObjectCreateStruct;
+
+ // Initialize an ObjectCreateStruct.
+ #define INIT_OBJECTCREATESTRUCT(theStruct) \
+ { \
+ memset(&theStruct, 0, sizeof(theStruct));\
+ VEC_SET(theStruct.m_Scale, 1, 1, 1); \
+ theStruct.m_Rotation.m_Spin = 1.0f; \
+ }
+
+
+ // Model hook.
+ #define MHF_USETEXTURE 1 // Use the texture for this model (if any).
+ typedef struct ModelHookData_t
+ {
+ HLOCALOBJ m_hObject;
+ unsigned long m_Flags; // Combination of MHF_ flags above.
+ unsigned long m_ObjectFlags; // The model's object flags. You can modify them
+ // in here without changing the model's flags
+ // permanently.
+ DVector *m_LightAdd; // RGB 0-255
+ } ModelHookData;
+
+
+ // Render modes are what are used to describe a video mode/video card.
+ typedef struct RMode_t
+ {
+ DBOOL m_bHardware;
+
+ char m_RenderDLL[200]; // What DLL this comes from.
+ char m_InternalName[100]; // This is what the DLLs use to identify a card.
+ char m_Description[100]; // This is a 'friendly' string describing the card.
+
+ DDWORD m_Width, m_Height, m_BitDepth;
+ struct RMode_t *m_pNext;
+ } RMode;
+
+ // The ID of the description string contained in render DLLs.
+ #define RDLL_DESCRIPTION_STRINGID 5
+
+
+ // Device input for device tracking
+ #define MAX_INPUT_BUFFER_SIZE 32
+
+ #define DEVICETYPE_KEYBOARD 1
+ #define DEVICETYPE_MOUSE 2
+ #define DEVICETYPE_JOYSTICK 4
+ #define DEVICETYPE_UNKNOWN 8
+
+ #define CONTROLTYPE_UNKNOWN 0 // unknown type
+ #define CONTROLTYPE_XAXIS 1 // horizontal axis, such as left-right motion of a mouse
+ #define CONTROLTYPE_YAXIS 2 // vertical axis, such as forward-backward motion of a mouse
+ #define CONTROLTYPE_ZAXIS 3 // z-axis, such as a wheel on a mouse or a throttle on a joystick
+ #define CONTROLTYPE_RXAXIS 4 // rotation around the x-axis
+ #define CONTROLTYPE_RYAXIS 5 // rotation around the y-axis
+ #define CONTROLTYPE_RZAXIS 6 // rotation around the z-axis
+ #define CONTROLTYPE_SLIDER 7 // a slider axis
+ #define CONTROLTYPE_BUTTON 8 // a mouse button
+ #define CONTROLTYPE_KEY 9 // a key on a keyboard
+ #define CONTROLTYPE_POV 10 // point-of-view indicator or "hat"
+
+ typedef struct DeviceInput_t
+ {
+ DDWORD m_DeviceType; // type of input device (DEVICETYPE_ defines above)
+ char m_DeviceName[128]; // name of input device
+
+ DDWORD m_ControlType; // type of control that changed (CONTROLTYPE_ defines above)
+ char m_ControlName[64]; // name of control that changed
+ DDWORD m_InputValue; // input value for the control
+ } DeviceInput;
+
+ // Device Object for listing objects on a particular device
+ typedef struct DeviceObject_t
+ {
+ DDWORD m_DeviceType; // type of input device (DEVICETYPE_ defines above)
+ char m_DeviceName[128]; // name of input device ("Keyboard", "Mouse", etc.)
+
+ DDWORD m_ObjectType; // type of object (CONTROLTYPE_ defines above)
+ char m_ObjectName[64]; // name of object ("x-axis", "button 0", etc.)
+
+ float m_RangeLow; // low end of range for this object
+ float m_RangeHigh; // high end of range for this object
+
+ struct DeviceObject_t* m_pNext;
+ } DeviceObject;
+
+ // Device Binding info for GetDeviceBindings()
+
+ #define MAX_ACTIONNAME_LEN 30
+ #define INPUTNAME_LEN 100
+
+ typedef struct GameAction_t
+ {
+ int nActionCode; // action number from config file
+ char strActionName[MAX_ACTIONNAME_LEN]; // name of action from config file
+ float nRangeLow; // low range if used (zero if not used)
+ float nRangeHigh; // high range if used (zero if not used)
+ struct GameAction_t* pNext; // next in list
+
+ } GameAction;
+
+ typedef struct DeviceBinding_t
+ {
+ char strDeviceName[INPUTNAME_LEN]; // name of device for this trigger
+ char strTriggerName[INPUTNAME_LEN]; // name of this trigger (device object name)
+ float nScale; // scale to multiply input by
+ float nRangeScaleMin; // min for range scale
+ float nRangeScaleMax; // max for range scale
+ float nRangeScalePreCenterOffset; // offset of cent value for input data
+ struct GameAction_t* pActionHead; // list of actions bound to this trigger
+ struct DeviceBinding_t* pNext; // next in list
+
+ } DeviceBinding;
+
+
+
+ // Structure used by a driver to describe a net service (such as ipx or tcp/ip).
+ #define MAX_NETSERVICENAME_LEN 128
+ class NetService
+ {
+ public:
+ HNETSERVICE m_handle;
+ DDWORD m_dwFlags; // Combination of NETSERVICE_ flags.
+ DGUID m_guidService;
+ char m_sName[MAX_NETSERVICENAME_LEN];
+ NetService *m_pNext;
+ };
+
+
+ // Structure used by a driver to describe a specific net session.
+ #define MAX_NETSESSIONNAME_LEN 4096
+ #define MAX_NETPASSWORD_LEN 64
+ #define MAX_HOSTIP_LEN 32
+ #define NO_HOST_PORT 0xFFFF
+
+ class NetSession
+ {
+ public:
+ NetSession() {Clear();}
+ virtual ~NetSession() {}
+
+ void Clear()
+ {
+ m_dwFlags = 0;
+ m_dwMaxPlayers = 0;
+ m_dwCurPlayers = 0;
+ m_Ping = 0;
+ m_sName[0] = 0;
+ m_sPassword[0] = 0;
+ m_HostIP[0] = 0;
+ m_HostPort = NO_HOST_PORT;
+ m_pNext = DNULL;
+ }
+
+ DDWORD m_dwFlags;
+ DGUID m_guidApp;
+ DGUID m_guidInst;
+ DDWORD m_dwMaxPlayers;
+ DDWORD m_dwCurPlayers;
+ DDWORD m_Ping; // Ping time in milliseconds.
+
+ // Host info. 0 length string and NO_HOST_PORT if not on TCP/IP.
+ char m_HostIP[MAX_HOSTIP_LEN];
+ DDWORD m_HostPort;
+
+ char m_sName[MAX_NETSESSIONNAME_LEN];
+ char m_sPassword[MAX_NETPASSWORD_LEN];
+ NetSession *m_pNext;
+ };
+
+
+ // Structure used by to instruct a driver to create/host a new session.
+ typedef struct NetHost_t
+ {
+ DDWORD m_Port; // Port if TCP/IP. If zero, it uses the default.
+ DDWORD m_dwFlags;
+ DDWORD m_dwMaxPlayers;
+ char m_sName[MAX_NETSESSIONNAME_LEN];
+ char m_sPassword[MAX_NETPASSWORD_LEN];
+
+ } NetHost;
+
+
+
+
+ // ---------------------------------------------------------------------- //
+ // Collision info
+ //
+ // Used to determine information in GetStandingOn or GetLastCollision
+ // ---------------------------------------------------------------------- //
+
+ class CollisionInfo
+ {
+ public:
+ // The blocking plane of whatever the object collided with. If both object's are non-solid, then this
+ // will have a normal vector of mag 0.
+ DPlane m_Plane;
+
+ // The object collided with.
+ HOBJECT m_hObject;
+
+ // If the m_hObject is the world, then m_hPoly contains a handle to the polygon the object collided with.
+ // Otherwise it is equal to DNULL.
+ HPOLY m_hPoly;
+
+ // Stopping velocity. Engine will automatically apply this velocity to stop object from continuing
+ // to collide with blocker.
+ DVector m_vStopVel;
+ };
+
+
+ // ---------------------------------------------------------------------- //
+ // Sound 3D Provider
+ //
+ // Used with GetSoundSW3DProviderList, GetSoundHW3DProviderList and
+ // ReleaseSound3DProviderList.
+ // ---------------------------------------------------------------------- //
+
+ // Sound 3D provider ID's
+ #define SOUND3DPROVIDERID_NONE 0
+ #define SOUND3DPROVIDERID_DS3D_HARDWARE 1
+ #define SOUND3DPROVIDERID_DS3D_HARDWARE_EAX 2
+ #define SOUND3DPROVIDERID_DS3D_SOFTWARE 3
+ #define SOUND3DPROVIDERID_A3D 4
+ #define SOUND3DPROVIDERID_INTEL_RSX 5
+ #define SOUND3DPROVIDERID_MILES3D 6
+ #define SOUND3DPROVIDERID_UNKNOWN 7
+
+ // Caps bits
+ #define SOUND3DPROVIDER_CAPS_REVERB (1<<0)
+
+ struct Sound3DProvider
+ {
+ DDWORD m_dwProviderID;
+ char m_szProvider[_MAX_PATH+1];
+ DDWORD m_dwCaps;
+ Sound3DProvider * m_pNextProvider;
+ };
+
+ // ---------------------------------------------------------------------- //
+ // Reverb properties
+ //
+ // Use this structure with SetReverb and GetReverb
+ // ---------------------------------------------------------------------- //
+
+ #define REVERBPARAM_VOLUME (1<<0) // m_fVolume field valid
+ #define REVERBPARAM_ACOUSTICS (1<<1) // m_dwAcoustics field valid
+ #define REVERBPARAM_REFLECTTIME (1<<2) // m_fReflectTime field valid
+ #define REVERBPARAM_DECAYTIME (1<<3) // m_fDecayTime field valid
+ #define REVERBPARAM_DAMPING (1<<4) // m_fDamping field valid
+ #define REVERBPARAM_ALL REVERBPARAM_VOLUME | REVERBPARAM_ACOUSTICS | REVERBPARAM_REFLECTTIME | REVERBPARAM_DECAYTIME | REVERBPARAM_DAMPING
+
+ // These are the valid values for m_dwAcoustics field
+ enum
+ {
+ REVERB_ACOUSTICS_GENERIC,
+ REVERB_ACOUSTICS_PADDEDCELL,
+ REVERB_ACOUSTICS_ROOM,
+ REVERB_ACOUSTICS_BATHROOM,
+ REVERB_ACOUSTICS_LIVINGROOM,
+ REVERB_ACOUSTICS_STONEROOM,
+ REVERB_ACOUSTICS_AUDITORIUM,
+ REVERB_ACOUSTICS_CONCERTHALL,
+ REVERB_ACOUSTICS_CAVE,
+ REVERB_ACOUSTICS_ARENA,
+ REVERB_ACOUSTICS_HANGAR,
+ REVERB_ACOUSTICS_CARPETEDHALLWAY,
+ REVERB_ACOUSTICS_HALLWAY,
+ REVERB_ACOUSTICS_STONECORRIDOR,
+ REVERB_ACOUSTICS_ALLEY,
+ REVERB_ACOUSTICS_FOREST,
+ REVERB_ACOUSTICS_CITY,
+ REVERB_ACOUSTICS_MOUNTAINS,
+ REVERB_ACOUSTICS_QUARRY,
+ REVERB_ACOUSTICS_PLAIN,
+ REVERB_ACOUSTICS_PARKINGLOT,
+ REVERB_ACOUSTICS_SEWERPIPE,
+ REVERB_ACOUSTICS_UNDERWATER,
+ REVERB_ACOUSTICS_DRUGGED,
+ REVERB_ACOUSTICS_DIZZY,
+ REVERB_ACOUSTICS_PSYCHOTIC,
+
+ REVERB_ACOUSTICS_COUNT // total number of room types
+ };
+
+ struct ReverbProperties
+ {
+ DDWORD m_dwParams; // Set the params bits for which fields are valid
+ float m_fVolume; // 0.0 - 1.0
+ DDWORD m_dwAcoustics; // One of the REVERB_ACOUSTICS_xxx values
+ float m_fReflectTime; // 0.0 - 5.0 Time for first reflection
+ float m_fDecayTime; // 0.1 - 20.0 Determines how quickly reflection diminish
+ float m_fDamping; // 0.0 - 2.0, == 1.0f is even damping, < 1.0f low frequencies dampen faster
+ // > 1.0f high frequencies dampen faster
+ };
+
+ // ---------------------------------------------------------------------- //
+ // Sound effects.
+ //
+ // The type of sounds are: ambient, local and 3D. The flags controlling
+ // these types are mutually exclusive. An ambient sound will have distance
+ // effects of rolloff, but no orientation effects. A local sound will have
+ // no orientation or distance effects and will be as if the sound was played
+ // inside the player's head. The 3d sound will have distance, orientation
+ // and doppler effects.
+ //
+ // Sounds are played from the beginning once the message reaches the client.
+ // If it is important that the playback be synchronized with the server's
+ // beginning time, then set PLAYSOUND_TIMESYNC. Normally, this is not
+ // that important. The server will use it internally if a client comes in
+ // after a sound has already been played.
+ //
+ // The server keeps a sound object if any of the following flags are set:
+ // PLAYSOUND_LOOP, PLAYSOUND_ATTACHED, PLAYSOUND_GETHANDLE, PLAYSOUND_TIMESYNC,
+ // PLAYSOUND_TIME. Server kept sounds will update clients that come and go.
+ // Non-server kept sounds are sent to the existing clients once, so the
+ // overhead is much less.
+ //
+ // Server kept sounds with PLAYSOUND_GETHANDLE must be removed by the game.
+ // Other server kept sounds are removed if they time out, or the object they
+ // are attached to is removed. When a sound is removed from the server,
+ // it tells the clients to remove their copies.
+ //
+ // Server tells clients about its sounds if the client object is within
+ // twice the outer radius of the sound. If local sound, then server always
+ // tells all the clients.
+ //
+ // Sounds that have a client object in m_hObject and PLAYSOUND_CLIENTLOCAL
+ // or PLAYSOUND_ATTACHED are played with PLAYSOUND_LOCAL for that particular client.
+ //
+ // The PLAYSOUND_CLIENT is for client initiated sounds only. When playing
+ // client side sounds, the PLAYSOUND_ATTACHED and PLAYSOUND_CLIENTLOCAL
+ // flags and m_wObjectID are ignored.
+ //
+ // Using PLAYSOUND_FILESTREAM tells the client to stream the file from disk.
+ // This prevents the loading of all of the sound data, but is slower.
+ // ---------------------------------------------------------------------- //
+
+ #define PLAYSOUND_LOCAL 0x0000 // Play sound locally (inside head)
+ #define PLAYSOUND_AMBIENT 0x0001 // Play sound as ambient sound.
+ #define PLAYSOUND_3D 0x0002 // Play sound as 3D sound.
+ #define PLAYSOUND_LOOP 0x0004 // Loop the sound.
+ #define PLAYSOUND_ATTACHED 0x0008 // Sounds position & orientation comes from object in m_hObject
+ #define PLAYSOUND_GETHANDLE 0x0010 // Handle requested
+ #define PLAYSOUND_TIME 0x0020 // Server must time sound
+ #define PLAYSOUND_CTRL_VOL 0x0040 // Control volume m_nVolume
+ #define PLAYSOUND_REVERB 0x0080 // Allow reverb
+ #define PLAYSOUND_CLIENT 0x0100 // Client side sound
+ #define PLAYSOUND_TIMESYNC 0x0200 // Playback synchronized with server clock
+ #define PLAYSOUND_FILESTREAM 0x0400 // Stream the file
+ #define PLAYSOUND_CLIENTLOCAL 0x0800 // Sound is played with PLAYSOUND_LOCAL for object in m_hObject
+
+ typedef struct PlaySoundInfo_t
+ {
+ // PLAYSOUND flags.
+ DDWORD m_dwFlags;
+
+ // File name of sound
+ char m_szSoundName[_MAX_PATH+1];
+
+ // SERVER ONLY: Object sound is attached to.
+ // Only needed if PLAYSOUND_ATTACHED or PLAYSOUND_CLIENTLOCAL set
+ HOBJECT m_hObject;
+
+ // Handle of sound
+ // Filled by PlaySound if PLAYSOUND_GETHANDLE set
+ HSOUNDDE m_hSound;
+
+ // Voice priority
+ // 0 is lowest priority
+ unsigned char m_nPriority;
+
+ // Maximum radius of sound. No sound outside this.
+ // Only needed if PLAYSOUND_3D or PLAYSOUND_AMBIENT
+ float m_fOuterRadius;
+
+ // Inner radius of sound. Sound at maximum volume inside this radius
+ // Only needed if PLAYSOUND_3D or PLAYSOUND_AMBIENT
+ float m_fInnerRadius;
+
+ // Volume of sound in percent [0,100].
+ // Only needed if PLAYSOUND_CTRL_VOL set, otherwise defaults 100
+ DBYTE m_nVolume;
+
+ // Position of sound.
+ // Only needed if PLAYSOUND_AMBIENT and PLAYSOUND_3D set
+ // Only needed if PLAYSOUND_ATTACHED cleared
+ DVector m_vPosition;
+
+ } PlaySoundInfo;
+
+ #define PLAYSOUNDINFO_COPY( dest, src ) \
+ memcpy(( void * )&( dest ), ( void * )&( src ), sizeof( PlaySoundInfo ));
+
+ #define PLAYSOUNDINFO_INIT(x) memset(&x, 0, sizeof(x));
+
+ // ---------------------------------------------------------------------- //
+ // InitSoundInfo
+ //
+ // Used to initialize the sound engine.
+ // ---------------------------------------------------------------------- //
+
+ // Maximum number of voices allowed for either sw or 3d
+ #define INITSOUNDINFO_MAXVOICES 128
+
+ // Used for m_dwFlags parameter
+ #define INITSOUNDINFOFLAG_CONVERT16TO8 (1<<0) // Convert all 16 bit buffers to 8 bit
+ #define INITSOUNDINFOFLAG_RELOADSOUNDS (1<<1) // Reload any sounds that exist before InitSound called
+
+ // Engine can fill these flags in the m_dwResults parameter
+ #define INITSOUNDINFORESULTS_REVERB (1<<0) // Provider chosen supports reverb
+
+ typedef struct InitSoundInfo_t
+ {
+ // Name of 3d provider to use
+ char m_sz3DProvider[_MAX_PATH+1];
+
+ // Number of sw voices
+ DBYTE m_nNumSWVoices;
+
+ // Number of 3D voices
+ DBYTE m_nNum3DVoices;
+
+ // Output sound format. Sample rate (8000, 11025, 22050 or
+ // 44100 kHz), Bits per sample (8 or 16)...
+ unsigned short m_nSampleRate;
+ unsigned short m_nBitsPerSample;
+
+ // Use INITSOUNDINFOFLAG_xxx flags
+ unsigned long m_dwFlags;
+
+ // Engine fills in this parameter with INITSOUNDINFORESULTS_xxx after InitSound is called.
+ unsigned long m_dwResults;
+
+ // Initial volume (0-100)
+ unsigned short m_nVolume;
+
+ // Distance factor in meters/game unit
+ float m_fDistanceFactor;
+
+ // Number of seconds to make streaming buffer. Don't go less than 0.2, though. The buffer
+ // is also limited by a minimum size of 20k.
+ float m_fMinStreamTime;
+
+ } InitSoundInfo;
+
+ // Initialize the InitSoundInfo structure to the default values...
+ #define INITSOUNDINFO_INIT( initSoundInfo ) \
+ initSoundInfo.m_sz3DProvider[0] = 0; \
+ initSoundInfo.m_nNumSWVoices = 32; \
+ initSoundInfo.m_nNum3DVoices = 0; \
+ initSoundInfo.m_nSampleRate = 22050; \
+ initSoundInfo.m_nBitsPerSample = 16; \
+ initSoundInfo.m_dwFlags = 0; \
+ initSoundInfo.m_nVolume = 100; \
+ initSoundInfo.m_fDistanceFactor = 1.0f; \
+ initSoundInfo.m_fMinStreamTime = 0.5f;
+
+
+ // ------------------------------------------------------------------ //
+ // Use this to start a game.
+ // ------------------------------------------------------------------ //
+
+ #define STARTGAME_HOST 0 // Start a world and host it (using dialogs).
+ #define STARTGAME_HOSTTCP 1 // Start a world and host on TCP/IP.
+
+ #define STARTGAME_CLIENT 2 // Connect to a server using dialogs.
+ #define STARTGAME_CLIENTTCP 3 // Connect to the first TCP/IP game it can find
+ // at m_pTCPAddress.
+
+ #define STARTGAME_NORMAL 4 // Start a normal game.
+ #define GAMEMODE_NONE 5 // (Used for GetGameMode, means we're not
+ // running a world or on a server yet).
+
+ #define SG_LOBBY 1 // Game was lobby-launched
+
+ #define MAX_SGR_STRINGLEN 100
+
+ class StartGameRequest
+ {
+ public:
+ StartGameRequest()
+ {
+ m_Type = STARTGAME_NORMAL;
+ m_WorldName[0] = 0;
+ m_TCPAddress[0] = 0;
+ m_RecordFilename[0] = 0;
+ m_PlaybackFilename[0] = 0;
+ m_flags = 0;
+ m_pGameInfo = DNULL;
+ m_GameInfoLen = 0;
+ m_pNetSession = DNULL;
+ m_pClientData = DNULL;
+ m_ClientDataLen = 0;
+ }
+
+ int m_Type;
+ char m_WorldName[MAX_SGR_STRINGLEN];
+ char m_TCPAddress[MAX_SGR_STRINGLEN]; // TCP/IP address, if any.
+
+ // Filename to record into, if any (set to 0 length if you don't want to record).
+ // NOTE: when this is set, the engine starts the server but doesn't run the level, you must
+ // send a message to the server telling it to load the world.
+ char m_RecordFilename[MAX_SGR_STRINGLEN];
+
+ // The filename of a recorded demo. If this is filled in, the engine starts a server
+ // and fills in m_WorldName with the world that the demo record uses. You need to
+ // send a message to the server telling it to load that world.
+ char m_PlaybackFilename[MAX_SGR_STRINGLEN];
+
+ NetSession *m_pNetSession; // This must be used with STARTGAME_CLIENT.
+ NetHost m_HostInfo; // This must be used with STARTGAME_HOST.
+ DDWORD m_flags; // Various flags
+
+ void *m_pGameInfo; // This data is copied over and can be accessed by
+ DDWORD m_GameInfoLen; // the server with ServerDE::GetGameInfo() (if you're
+ // running a local or hosted game).
+
+ // This data gets sent up and passed into OnClientEnterWorld on the server.
+ void *m_pClientData;
+ DDWORD m_ClientDataLen;
+ };
+
+
+ // The new console parsing thing.
+ class ConParse
+ {
+ public:
+
+ ConParse() {m_pCommandPos = NULL;}
+ ConParse(char *pBuffer) {m_pCommandPos = pBuffer;}
+
+ // Sets it up to parse the specified buffer.
+ void Init(char *pBuffer) {m_pCommandPos = pBuffer;}
+
+ // The parsed arguments.
+ char *m_Args[PARSE_MAXTOKENS];
+ int m_nArgs;
+
+ // Used internally by the engine.
+ public:
+
+ // Parse the next set of tokens. Returns TRUE if it parsed anything.
+ DBOOL Parse();
+
+ // Parses until it finds tokens with pLookFor as the first one.
+ // You can use this just like Parse like this:
+ // while(ParseFind("AmbientLight", FALSE)) { ... }
+ DBOOL ParseFind(char *pLookFor, DBOOL bCaseSensitive, DDWORD minTokens=1);
+
+ private:
+
+ char *m_pCommandPos;
+ char m_ArgBuffer[PARSE_MAXTOKENS*PARSE_MAXTOKENSIZE];
+ };
+
+
+ // ---------------------------------------------------------------------- //
+ // Intersection stuff.
+ // ---------------------------------------------------------------------- //
+
+ // Return DTRUE to select this object and DFALSE to not select it.
+ typedef DBOOL (*ObjectFilterFn)(HOBJECT hObj, void *pUserData);
+
+
+ // Pass this in to the IntersectSegment routine.
+ class IntersectQuery
+ {
+ public:
+ IntersectQuery()
+ {
+ m_Flags = 0;
+ m_FilterFn = 0;
+ }
+
+ // Start and end points.
+ DVector m_From;
+ DVector m_To;
+
+ // Only used for CastRay.. this is the direction the ray should be cast in.
+ // This doesn't need to be normalized.
+ DVector m_Direction;
+
+ // A combination of the intersect flags (in de_codes.h).
+ DDWORD m_Flags;
+
+ // If this is not NULL, then it'll call this function when it has a
+ // POSSIBLE object intersection (it doesn't know if it really intersects
+ // yet when it calls this). If you return FALSE from this function,
+ // then it will ignore the object and continue on.
+ ObjectFilterFn m_FilterFn;
+
+ // Passed into pUserData of the filter function.
+ void *m_pUserData;
+ };
+
+
+ typedef struct IntersectInfo_t
+ {
+ // Point of intersection.
+ DVector m_Point;
+
+ // Plane of intersection.
+ DPlane m_Plane;
+
+ // Object it hit.
+ HOBJECT m_hObject;
+
+ // The polygon it hit (if it's a world poly).
+ // Value is INVALID_HPOLY if it didn't hit one.
+ HPOLY m_hPoly;
+
+ // Surface flags of what it hit (these aren't object flags, and are
+ // only set if it hit the world or a WorldModel).
+ DDWORD m_SurfaceFlags;
+ } IntersectInfo;
+
+ #define ClientIntersectInfo IntersectInfo
+ #define ClientIntersectQuery IntersectQuery
+
+
+#endif // __BASEDEFS_H__
+
+
diff --git a/AppHeaders/basetypes_de.h b/AppHeaders/basetypes_de.h
new file mode 100644
index 0000000..ea1ca25
--- /dev/null
+++ b/AppHeaders/basetypes_de.h
@@ -0,0 +1,412 @@
+
+#ifndef __BASETYPES_DE_H__
+#define __BASETYPES_DE_H__
+
+
+ #include <math.h>
+
+ #include "de_codes.h"
+ #include "dstream.h"
+
+
+ #define INLINE_FN __inline
+ #define _LITHTECH_
+
+
+ // Base types.
+ #define DNULL 0
+ #define DBOOL char
+ #define DTRUE 1
+ #define DFALSE 0
+ #define DDWORD unsigned long
+ #define D_WORD unsigned short
+ #define DBYTE unsigned char
+ typedef float DFLOAT;
+
+
+ // Reference to a surface.
+ typedef unsigned long HPOLY;
+ #define INVALID_HPOLY 0xFFFFFFFF
+
+
+ // Globally unique identifier.
+ typedef struct DGUID_t
+ {
+ unsigned long a;
+ unsigned short b;
+ unsigned short c;
+ unsigned char d[8];
+
+ } DGUID;
+
+
+ // Maximum number of sky objects.
+ #define MAX_SKYOBJECTS 30
+
+
+ // Parsing stuff.
+ #define PARSE_MAXTOKENS 64
+ #define PARSE_MAXTOKENSIZE 80
+
+ // Helpful math definitions.
+ #define MATH_PI 3.141592653589793f
+ #define MATH_HALFPI 1.570796326795f
+ #define MATH_CIRCLE 6.283185307178f
+ #define MATH_ONE_OVER_PI 0.3183098861839f
+ #define MATH_EPSILON 0.00000000001f
+ #define MATH_DEGREES_TO_RADIANS(x) ((x) * 0.01745329251994f)
+
+ #define MATH_ONE_OVER_255 0.003921568627451f
+
+
+ #define DDIFF(a,b) (((a) < (b)) ? ((b) - (a)) : ((a) - (b)))
+ #define DMIN(a,b) ((a) < (b) ? (a) : (b))
+ #define DMAX(a,b) ((a) > (b) ? (a) : (b))
+ #define DABS(a) ((a) > 0 ? (a) : -(a))
+ #define DCLAMP(a, min, max) ((a) < (min) ? (min) : ((a) > (max) ? (max) : (a)))
+ #define DLERP(min, max, t) ((min) + ((max) - (min)) * (t))
+
+
+
+ #include "dvector.h"
+
+
+ #define ROT_COPY(dest, src) \
+ {\
+ VEC_COPY((dest).m_Vec, (src).m_Vec);\
+ (dest).m_Spin = (src).m_Spin;\
+ }
+
+ #define PLANE_COPY(dest, src) \
+ {\
+ VEC_COPY((dest).m_Normal, (src).m_Normal)\
+ (dest).m_Dist = (src).m_Dist;\
+ }
+
+ #define PLANE_SET(plane, _x, _y, _z, _dist) \
+ {\
+ (plane).m_Normal.x = (_x);\
+ (plane).m_Normal.y = (_y);\
+ (plane).m_Normal.z = (_z);\
+ (plane).m_Dist = (_dist);\
+ }
+
+ #define MAT_COPY(dest, src) \
+ {\
+ (dest).m[0][0] = (src).m[0][0];\
+ (dest).m[0][1] = (src).m[0][1];\
+ (dest).m[0][2] = (src).m[0][2];\
+ (dest).m[0][3] = (src).m[0][3];\
+ \
+ (dest).m[1][0] = (src).m[1][0];\
+ (dest).m[1][1] = (src).m[1][1];\
+ (dest).m[1][2] = (src).m[1][2];\
+ (dest).m[1][3] = (src).m[1][3];\
+ \
+ (dest).m[2][0] = (src).m[2][0];\
+ (dest).m[2][1] = (src).m[2][1];\
+ (dest).m[2][2] = (src).m[2][2];\
+ (dest).m[2][3] = (src).m[2][3];\
+ \
+ (dest).m[3][0] = (src).m[3][0];\
+ (dest).m[3][1] = (src).m[3][1];\
+ (dest).m[3][2] = (src).m[3][2];\
+ (dest).m[3][3] = (src).m[3][3];\
+ }
+
+ #define MAT_SET(dest, \
+ e00, e01, e02, e03,\
+ e10, e11, e12, e13,\
+ e20, e21, e22, e23,\
+ e30, e31, e32, e33)\
+ {\
+ (dest).m[0][0] = e00; (dest).m[0][1] = e01; (dest).m[0][2] = e02; (dest).m[0][3] = e03;\
+ (dest).m[1][0] = e10; (dest).m[1][1] = e11; (dest).m[1][2] = e12; (dest).m[1][3] = e13;\
+ (dest).m[2][0] = e20; (dest).m[2][1] = e21; (dest).m[2][2] = e22; (dest).m[2][3] = e23;\
+ (dest).m[3][0] = e30; (dest).m[3][1] = e31; (dest).m[3][2] = e32; (dest).m[3][3] = e33;\
+ }
+
+
+ // Get the distance from a point to a plane.
+ #define DIST_TO_PLANE(vec, plane) ( VEC_DOT((plane).m_Normal, (vec)) - (plane).m_Dist )
+
+ // Initializes the rotation to look down the positive Z axis.
+ #define ROT_INIT(r) \
+ {\
+ (r).m_Vec.x = (r).m_Vec.y = (r).m_Vec.z = 0.0f;\
+ (r).m_Spin = 1.0f;\
+ }
+
+
+ // Used for resizing arrays.. mostly for internal DirectEngine stuff.
+ #define GENERIC_REMOVE(theArray, iIndex, nElements) \
+ ASSERT(nElements > 0);\
+ memmove(&theArray[iIndex], &theArray[iIndex+1], sizeof(theArray[0]) * (nElements-iIndex-1));\
+ nElements--;
+
+ #define GENERIC_INSERT(type, theArray, nElements, iIndex, value) \
+ {\
+ type *pNewArray = (type*)malloc(sizeof(type) * (nElements+1));\
+ memcpy(pNewArray, theArray, nElements * sizeof(type));\
+ memmove(&pNewArray[iIndex+1], &pNewArray[iIndex], sizeof(type)*(nElements-iIndex));\
+ memcpy(&pNewArray[iIndex], &value, sizeof(type));\
+ free(theArray);\
+ theArray = pNewArray;\
+ ++nElements;\
+ }
+
+ #define GENERIC_APPEND(type, theArray, nElements, value) \
+ GENERIC_INSERT(type, theArray, nElements, nElements, value);
+
+ #define DTOCVEC(_vec) (*((CVector*)&(_vec)))
+ #define CTODVEC(_vec) (*((DVector*)&(_vec)))
+
+
+
+ typedef struct
+ {
+ float x, y, z; // RGB 0-255
+ float a; // Alpha 0-255
+ } PGColor;
+
+ typedef struct DRotation_t
+ {
+ DRotation_t() {}
+
+ DRotation_t(float x, float y, float z, float spin)
+ {
+ m_Vec.x = x;
+ m_Vec.y = y;
+ m_Vec.z = z;
+ m_Spin = spin;
+ }
+
+ // <vector>, spin
+ DVector m_Vec;
+ float m_Spin;
+ } DRotation;
+
+ typedef struct DPlane_t
+ {
+ DPlane_t() {}
+ DPlane_t(float x, float y, float z, float dist)
+ {
+ m_Normal.x = x;
+ m_Normal.y = y;
+ m_Normal.z = z;
+ m_Dist = dist;
+ }
+
+ DVector m_Normal;
+ float m_Dist;
+ } DPlane;
+
+ typedef struct DFloatPt_t
+ {
+ float x, y;
+ } DFloatPt;
+
+ class DIntPt
+ {
+ public:
+ int x, y;
+ };
+
+ typedef struct DWarpPt_t
+ {
+ float source_x, source_y;
+ float dest_x, dest_y;
+ } DWarpPt;
+
+ typedef struct DRect_t
+ {
+ int left, top, right, bottom;
+ } DRect;
+
+ typedef struct ArgList_t
+ {
+ char **argv;
+ int argc;
+ } ArgList;
+
+ // Surface data.
+ typedef struct SurfaceData_t
+ {
+ DVector O, P, Q; // Texture vectors.
+ unsigned char m_EffectParam; // Effect parameter.
+ } SurfaceData;
+
+ // Sky definition.
+ typedef struct SkyDef_t
+ {
+ DVector m_Min, m_Max; // Box corners (in world coordinates).
+ DVector m_ViewMin, m_ViewMax; // View min and max. The viewer's position
+ // in the main world is squished into this
+ // box so you can get a tiny amount of parallax.
+ } SkyDef;
+
+
+ #include "matrix_ops.h"
+ #include "dlink.h"
+
+ // Note: this is only used internally by the engine.
+ // A nexus is something that leeches can attach to. Then when the nexus is
+ // destroyed, the leeches get a message so they can uninitialize whatever
+ // they need.
+ typedef struct Nexus_t
+ {
+ CheapDLink m_LeechHead;
+ void *m_pData; // User data.. set in nexus_Init.
+ } Nexus;
+
+
+
+ typedef DDWORD HMODELANIM;
+ typedef void (*ConsoleProgramFn)(int argc, char **argv);
+
+
+ // Object flags.
+ #define FLAG_VISIBLE (1<<0)
+
+ #define FLAG_SHADOW (1<<1) // Does this model cast shadows?
+ #define FLAG_UNSIGNED (1<<1) // Tells the polygrid to use unsigned bytes for its data.
+
+ #define FLAG_MODELTINT (1<<2) // If this is set, it draws a model in 2 passes. In the
+ // second pass, it scales down the color with ColorR,
+ // ColorG, and ColorB. This is used to tint the skins
+ // in multiplayer. Note: it uses powers of 2 to determine
+ // scale so the color scale maps like this:
+ // > 253 = 1.0
+ // > 126 = 0.5
+ // > 62 = 0.25
+ // > 29 = 0.12
+ // otherwise 0
+
+ #define FLAG_CASTSHADOWS (1<<3) // Should this light cast shadows (slower)?
+ #define FLAG_ROTATEABLESPRITE (1<<3) // Sprites only.
+ #define FLAG_MODELGOURAUDSHADE (1<<3) // Models only.
+ #define FLAG_UPDATEUNSEEN (1<<3) // Particle systems only.
+ // If this is set, the engine will update
+ // particles even when they're invisible.
+ // You should check FLAG_WASDRAWN
+ // on any particle systems you're iterating
+ // over so you don't update invisible ones.
+
+ #define FLAG_SOLIDLIGHT (1<<4) // Use the 'fastlight' method for this light.
+ #define FLAG_SPRITECHROMAKEY (1<<4) // Disabled.. doesn't do anything anymore.
+ #define FLAG_MODELWIREFRAME (1<<4)
+ #define FLAG_WASDRAWN (1<<4) // The engine sets this if a particle system
+ // or PolyGrid was drawn. You can use this to
+ // determine whether or not to do some expensive
+ // calculations on it.
+
+ #define FLAG_GLOWSPRITE (1<<5) // Shrinks the sprite as the viewer gets nearer.
+ #define FLAG_ONLYLIGHTWORLD (1<<5) // Lights only - tells it to only light the world.
+ #define FLAG_ENVIRONMENTMAP (1<<5) // Environment map the model.
+ #define FLAG_ENVIRONMENTMAPONLY (1<<5) // For PolyGrids - says to only use the environment map (ignore main texture).
+
+ #define FLAG_SPRITEBIAS (1<<6) // Biases the Z towards the view so a sprite doesn't clip as much.
+ #define FLAG_DONTLIGHTBACKFACING (1<<6) // Lights only - don't light backfacing polies.
+ #define FLAG_REALLYCLOSE (1<<6) // Used for models really close to the view (like PV weapons).
+ // Must use tricks so it doesn't clip off.
+
+ #define FLAG_FOGLIGHT (1<<7) // Use on OT_LIGHTS. This light generates fog instead of light.
+ #define FLAG_ANIMTRANSITION (1<<7) // Does a 200ms transition between model animations.
+ #define FLAG_SPRITE_NOZ (1<<7) // Disable Z read/write on sprite (good for lens flares).
+ // These sprites must not be chromakeyed.
+
+ #define FLAG_FULLPOSITIONRES (1<<8) // LT normally compresses the position and rotation info
+ // to reduce packet size. Some things must be exact
+ // (like some WorldModels) so this will
+ // enlarge the packets for better accuracy.
+
+ #define FLAG_NOLIGHT (1<<9) // Just use the object's color and global light scale.
+ // (Don't affect by area or by dynamic lights).
+
+ #define FLAG_HARDWAREONLY (1<<10) // Don't draw this object if we're using software rendering.
+
+ #define FLAG_YROTATION (1<<11) // Uses minimal network traffic to represent rotation
+ // (1 byte instead of 3, but only rotates around the Y axis).
+
+ #define FLAG_SKYOBJECT (1<<12) // Don't render this object thru the normal stuff,
+ // only render it when processing sky objects.
+
+ #define FLAG_SOLID (1<<13) // Object can't go thru other solid objects.
+
+ #define FLAG_BOXPHYSICS (1<<14) // Use simple box physics on this object (used for WorldModels and containers).
+
+ #define FLAG_CLIENTNONSOLID (1<<15) // This object is solid on the server and nonsolid on the client.
+
+ // Which flags the client knows about.
+ #define CLIENT_FLAGMASK (FLAG_VISIBLE|FLAG_SHADOW|FLAG_MODELTINT|\
+ FLAG_ROTATEABLESPRITE|FLAG_SOLIDLIGHT|\
+ FLAG_REALLYCLOSE|FLAG_SPRITE_NOZ|\
+ FLAG_FULLPOSITIONRES|FLAG_NOLIGHT|FLAG_ENVIRONMENTMAP|\
+ FLAG_HARDWAREONLY|FLAG_YROTATION|FLAG_SKYOBJECT|\
+ FLAG_SOLID|FLAG_BOXPHYSICS|FLAG_CLIENTNONSOLID)
+
+ // Server only flags.
+ #define FLAG_TOUCH_NOTIFY (1<<16) // Gets touch notification.
+ #define FLAG_GRAVITY (1<<17) // Gravity is applied.
+ #define FLAG_STAIRSTEP (1<<18) // Steps up stairs.
+ #define FLAG_MODELKEYS (1<<19) // The object won't get get MID_MODELSTRINGKEY messages unless
+ // it sets this flag.
+ #define FLAG_KEEPALIVE (1<<20) // Save and restore this object when switching worlds.
+ #define FLAG_GOTHRUWORLD (1<<21) // Object can pass through world
+ #define FLAG_RAYHIT (1<<22) // Object is hit by raycasts.
+ #define FLAG_DONTFOLLOWSTANDING (1<<23) // Dont follow the object this object is standing on.
+ #define FLAG_FORCECLIENTUPDATE (1<<24) // Force client updates even if the object is OT_NORMAL or invisible.
+ // Use this whenever possible.. it saves cycles.
+ #define FLAG_NOSLIDING (1<<25) // Object won't slide agaist polygons
+
+ #define FLAG_POINTCOLLIDE (1<<26) // Uses much (10x) faster physics for collision detection, but the
+ // object is a point (dims 0,0,0). Standing info is not set when
+ // this flag is set.
+
+ #define FLAG_REMOVEIFOUTSIDE (1<<27) // Remove this object automatically if it gets outside the world.
+
+ #define FLAG_FORCEOPTIMIZEOBJECT (1<<28) // Force the engine to optimize this object
+ // as if the FLAG_OPTIMIZEOBJECT flags were
+ // cleared. This can be used if you have a visible
+ // object that's an attachment but it doesn't need
+ // touch notifies or raycast hits (like a gun-in-hand).
+
+ // Internal flags. Descriptions are there to help the DE developers remember what
+ // they're there for, NOT for general use!
+ #define FLAG_INTERNAL1 (1<<29) // (Did the renderer see the object).
+ #define FLAG_INTERNAL2 (1<<30) // (Used by ClientDE::FindObjectsInSphere).
+ #define FLAG_LASTFLAG (1<<31)
+
+
+ // If you clear these flags (flags &= ~FLAG_OPTIMIZEMASK) and the object doesn't have
+ // a special effect message, the engine never even iterates over the object for movement,
+ // raycasting, visibility, etc. Use this whenever you can.
+ #define FLAG_OPTIMIZEMASK (FLAG_VISIBLE|FLAG_SOLID|FLAG_TOUCH_NOTIFY|\
+ FLAG_RAYHIT|FLAG_FORCECLIENTUPDATE|FLAG_GOTHRUWORLD)
+
+
+ // Different object types. Some can only be created on the client.
+ #define OT_NORMAL 0 // Invisible object. Note, client's aren't told about
+ // these when they're created on the server!
+ #define OT_MODEL 1 // Model object.
+ #define OT_WORLDMODEL 2 // WorldModel.
+ #define OT_SPRITE 3 // Sprite.
+ #define OT_LIGHT 4 // Dynamic light.
+
+ #define OT_CAMERA 5 // Camera.
+ #define OT_PARTICLESYSTEM 6 // Particle system.
+ #define OT_POLYGRID 7 // Poly grid.
+ #define OT_LINESYSTEM 8 // Line system.
+ #define OT_CONTAINER 9 // Container.
+ #define NUM_OBJECTTYPES 10 // NOTE: the high bit of the object type is reserved
+ // for the engine's networking.
+
+ // Size defines used for Parse functions
+ // Use these to size your argument buffer and argument pointer
+ // buffer accordingly.
+ #define PARSE_MAXARGS 30
+ #define PARSE_MAXARGLEN 80
+
+
+#endif
+
diff --git a/AppHeaders/client_de.h b/AppHeaders/client_de.h
new file mode 100644
index 0000000..e001b81
--- /dev/null
+++ b/AppHeaders/client_de.h
@@ -0,0 +1,1152 @@
+
+
+#ifndef __CLIENT_DE_H__
+#define __CLIENT_DE_H__
+
+
+ #include "basedefs_de.h"
+ #include "clientshell_de.h"
+ #include "common_de.h"
+ #include "CSBase.h"
+
+
+
+ // Particle system flags. Each one slows it down a little more
+ // except for PS_NEVERDIE which speeds it up..
+ #define PS_BOUNCE 1 // Do they bounce?
+ #define PS_SHADOWS 2 // Enable shadows.
+ #define PS_NEVERDIE 4 // The particles never die (and it doesn't have to check).
+ #define PS_DUMB 8 // The engine leaves the system alone.. you must
+ // update and move them.
+
+
+ class SpriteControl;
+
+
+
+ // The particle structure for particle systems.
+ typedef struct DEParticle_t
+ {
+ DVector m_Velocity;
+ DVector m_Color; // Particle colors are 0-255.
+ struct DEParticle_t *m_pNext;
+ } DEParticle;
+
+
+ // The line structure for line system.
+ typedef struct DELinePt_t
+ {
+ DVector m_Pos;
+ float r, g, b, a; // Values 0-1.
+ } DELinePt;
+
+ typedef struct DELine_t
+ {
+ DELinePt m_Points[2];
+ } DELine;
+
+ DEFINE_HANDLE_TYPE(HDELINE)
+
+ // ------------------------------------------------------------------ //
+ // Client-side object flags.
+ // ------------------------------------------------------------------ //
+
+ // The engine calls ClientShell::OnObjectRemove() when the object goes away.
+ #define CF_NOTIFYREMOVE (1<<0)
+ #define CF_NOTIFYMODELKEYS (1<<1) // Calls ClientShellDE::OnModelKey when it hits model keys.
+ #define CF_DONTSETDIMS (1<<2) // The engine automatically sets the object's dims to its
+ // animation dims. This tells it not to.
+
+
+
+
+ // Music info
+
+ #define MUSIC_IMMEDIATE 0
+ #define MUSIC_NEXTMEASURE 1
+ #define MUSIC_NEXTSONG 2
+ #define MUSIC_QUEUE 3
+
+
+ // Used in AddSurfaceEffect.
+ typedef struct SurfaceEffectDesc_t
+ {
+ char *m_pName; // You don't have to allocate this..
+
+ // If you return NULL from here, the effect won't be initialized.
+ void* (*InitEffect)(struct SurfaceData_t *pSurfaceData, int argc, char **argv);
+ int (*UpdateEffect)(struct SurfaceData_t *pSurfaceData, void *pData); // pData is what you returned from InitEffect.
+ // Return 1 if you changed the surface.
+ void (*TermEffect)(void *pData);
+ } SurfaceEffectDesc;
+
+
+ // ------------------------------------------------------------------ //
+ // Model hook stuff.
+ // ------------------------------------------------------------------ //
+
+ typedef void (*ModelHookFn)(struct ModelHookData_t *pData, void *pUser);
+
+
+
+ class CPhysicsLT;
+
+
+ // ------------------------------------------------------------------ //
+ // ClientDE interface. This is what the ClientShells and special
+ // effect plugins use to do the interface and client objects for the game.
+ // ------------------------------------------------------------------ //
+
+ class ClientDE : public CSBase
+ {
+ friend class CClientMgr;
+
+ protected:
+
+ virtual ~ClientDE() {}
+
+
+ public:
+
+
+
+ // Access to the smaller interfaces.
+
+ CommonLT* Common() {return m_pCommonLT;}
+ CPhysicsLT* Physics() {return m_pPhysicsLT;}
+
+
+ // Connection stuff.
+
+ // Tries to start the game in the mode you specify.
+ // This will keep the existing game running until it successfully starts
+ // the new game.. ie: if there's an error starting the new world, it
+ // will still leave the current one running and put up an error message.
+ DRESULT (*StartGame)(StartGameRequest *pRequest);
+
+ // Find out what the current game mode is (how we started the last
+ // game with StartGame or thru the console). Fills in mode with
+ // one of the STARTGAME_ defines above.
+ DRESULT (*GetGameMode)(int *mode);
+
+ // Gets the local client ID.
+ // Returns DE_NOTCONNECTED if we're not on a server or haven't
+ // gotten a client ID yet.
+ DRESULT (*GetLocalClientID)(DDWORD *pID);
+
+ DBOOL (*IsConnected)(); // Are we on a server currently?
+
+ // Disconnect from the server we're on (if any).
+ // NOTE: this will destroy any client-side objects you've created!
+ void (*Disconnect)();
+
+ // Shuts down the app (not right away, but after the current update).
+ void (*Shutdown)();
+
+ // Shuts down the app (not right away, but after the current update).
+ void (*ShutdownWithMessage)( char *pMsg, ... );
+
+ // OBSOLETE: use the CommonDE one.
+ virtual DRESULT GetPointStatus(DVector *pPoint)=0;
+
+ // Get the shade (RGB, 0-255) at the point you specify.
+ // Returns DE_NOTINWORLD if the point is outside the world.
+ virtual DRESULT GetPointShade(DVector *pPoint, DVector *pColor)=0;
+
+
+ // Renderer management.
+
+ // Flip the screen. Flags are a combination of FLIPSCREEN_ flags in de_codes.
+ // Returns LT_OK or LT_NOTINITIALIZED.
+ DRESULT (*FlipScreen)(DDWORD flags);
+
+ // Clear the backbuffer. Pass in NULL to clear the whole screen.
+ // Flags is a combination of the CLEARSCREEN_ flags in de_codes.h.
+ // Returns LT_OK or LT_NOTINITIALIZED.
+ DRESULT (*ClearScreen)(DRect *pClearRect, DDWORD flags);
+
+ // You must be in a Start3D()/End3D() block in order to render
+ // through any cameras.
+ // Returns LT_OK or LT_NOTINITIALIZED or LT_ALREADYIN3D.
+ DRESULT (*Start3D)();
+
+ // Render from the camera's position into its rectangle.
+ // Returns LT_OK or LT_NOTINITIALIZED or LT_NOTIN3D.
+ DRESULT (*RenderCamera)(HLOCALOBJ hCamera);
+
+ // Renders the list of objects through the given camera.
+ // Returns LT_OK or LT_NOTINITIALIZED or LT_NOTIN3D.
+ DRESULT (*RenderObjects)(HLOCALOBJ hCamera, HLOCALOBJ *pObjects, int nObjects);
+
+ // You must be in a StartOptimized2D()/EndOptimized2D() block to draw any optimized 2D surfaces.
+ DRESULT (*StartOptimized2D)();
+ DRESULT (*EndOptimized2D)();
+
+ // Returns LT_OK or LT_NOTINITIALIZED or LT_NOTIN3D.
+ DRESULT (*End3D)();
+
+ // Get a (NULL-terminated) list of supported render modes.
+ RMode* (*GetRenderModes)();
+ void (*RelinquishRenderModes)(RMode *pModes);
+
+ // Fills in the current render mode.
+ DRESULT (*GetRenderMode)(RMode *pMode);
+
+ // Goes into the requested render mode.
+ // Returns LT_OK if successful. Note: it may not have set the _exact_ mode you
+ // requested. You can check with GetRenderMode() to see what the new mode is.
+ // Returns LT_KEPTSAMEMODE if it couldn't set the mode requested, but
+ // was able to restore the previous mode.
+ // Returns DE_UNABLETORESTOREVIDEO if it couldn't set the mode and couldn't
+ // restore the video mode (in which case it will give a message and shutdown
+ // afterwards).
+ DRESULT (*SetRenderMode)(RMode *pMode);
+
+ // Shutdown the renderer. flags is a combination of the RSHUTDOWN_ flags in de_codes.h.
+ // The renderer won't come back until you call SetRenderMode().
+ DRESULT (*ShutdownRender)(DDWORD flags);
+
+
+ // File management.
+
+ // Open a file up. Pass in the relative filename.
+ // Free the file by calling DStream::Release().
+ virtual DRESULT OpenFile(char *pFilename, DStream **pStream)=0;
+
+ // Get a list of files/directories in a directory (pass in "" to start with).
+ // The list is a noncircular linked list with DNULL terminating it.
+ FileEntry* (*GetFileList)(char *pDirName);
+
+ // Use FreeFileList when you're done with each list you get.
+ void (*FreeFileList)(FileEntry *pHead);
+
+ // Get the world info string from the World Info dialog in DEdit.
+ // Returns DE_NOTFOUND if it can't open the file and DE_INVALIDWORLDFILE
+ // if the file is an invalid version.
+ DRESULT (*GetWorldInfoString)(char *pFilename, char *pInfoString, DDWORD maxLen, DDWORD *pActualLen);
+
+ // Read/write configuration files. Returns LT_ERROR if the file doesn't exist
+ // or if it can't open the file for writing.
+ DRESULT (*ReadConfigFile)(char *pFilename);
+ DRESULT (*WriteConfigFile)(char *pFilename);
+
+
+ // Interface stuff.
+
+ // offsets is NUM_AXIS_OFFSETS large.
+ void (*GetAxisOffsets)(DFLOAT *offsets);
+
+ void (*PlayJoystickEffect)(char *pEffectName, float x, float y);
+
+
+ // Music functions.
+
+ DBOOL (*InitMusic)( char *szMusicDLL );
+
+ // Sets the directory to find music data files.
+ // IMA only.
+ DBOOL (*SetMusicDirectory)( char *szMusicDirectory );
+
+ // Downloads DLS.
+ // szDLSFile is the Downloadable Synthizer file containing the waves for
+ // instruments. szStyleFile is a style file, that is a compainion to the
+ // DLS file. It must contain bands that define the program changes for
+ // each instrument in DLS...
+ // IMA only.
+ DBOOL (*InitInstruments)( char *szDLSFile, char *szStyleFile );
+
+ // Cache in a song file.
+ DBOOL (*LoadSong)(char *szSong);
+
+ // Remove all the songs from memory...
+ void (*DestroyAllSongs)();
+
+ // Plays a playlist. All songs will be played until end of list.
+ // Arguments:
+ // szPlayList - Name of playlist.
+ // szTransition - Name of transition song to play before playlist starts. IMA only.
+ // bLoop - Loop the list.
+ // dwBoundaryFlags - Can be MUSIC_IMMEDIATE, MUSIC_MEASURE, MUSIC_SONG, MUSIC_QUEUE. Valid for IMA only.
+ DBOOL (*PlayList)( char *szPlayList, char *szTransition, DBOOL bLoop, DDWORD dwBoundaryFlags );
+
+ // Plays a musical break.
+ // IMA only.
+ // Arguments:
+ // szSong - Name of song.
+ // dwBoundaryFlags - Can be MUSIC_IMMEDIATE, MUSIC_MEASURE, MUSIC_SONG, MUSIC_QUEUE. Valid for IMA only.
+ DBOOL (*PlayBreak)( char *szSong, DDWORD dwBoundaryFlags );
+
+ // Stops music.
+ // Arguments:
+ // dwBoundaryFlags - Can be MUSIC_IMMEDIATE, MUSIC_MEASURE, MUSIC_SONG, MUSIC_QUEUE. Valid for IMA only.
+ void (*StopMusic)( DDWORD dwBoundaryFlags );
+
+ // Pause music. Can be resumed...
+ DBOOL (*PauseMusic)();
+
+ // Resume music...
+ DBOOL (*ResumeMusic)();
+
+ // Create and add to playlists....
+ // Arguments:
+ // szPlayList - Name of playlist.
+ // szSong - Name of song to add.
+ DBOOL (*AddSongToPlayList)(char *szPlayList, char *szSong);
+
+ // Removes a whole playlist...
+ // Arguments:
+ // szPlayList - Name of playlist.
+ void (*DeletePlayList)(char *szPlayList);
+
+ // Plays a motif.
+ // Ima only.
+ // Arguments:
+ // szMotif - name of motif.
+ // bLoop - Loop the motif.
+ DBOOL (*PlayMotif)(char *szMotif, DBOOL bLoop);
+
+ // Stops a motif for IMA.
+ // IMA only.
+ // Arguments:
+ // szMotif - name of motif.
+ void (*StopMotif)(char *szMotif);
+
+ // Volume range is 0-off, 100-full.
+ short (*GetMusicVolume)();
+ void (*SetMusicVolume)( short wVolume );
+
+
+ // Sound functions.
+
+ // Gets a list of the 3d sound providers available on system. Choose one pass it in the
+ // InitSoundInfo structure. Use bVerify to tell the engine not to report providers that
+ // aren't completely supported on the system. This takes longer and causes speaker popping.
+ // Games should only need to do this when a different provider is chosen. EAX support
+ // can only be checked when the provider is opened, so without the bVerify, the
+ // SOUND3DPROVIDER_CAPS_REVERB cannot be set. InitSound will report this info in the
+ // m_dwResults flags.
+ // Be sure to release both lists with ReleaseSound3DProviderList.
+ DRESULT (*GetSound3DProviderLists)( Sound3DProvider *&pSound3DProviderList, DBOOL bVerify );
+ void (*ReleaseSound3DProviderList)( Sound3DProvider *pSound3DProviderList );
+
+ // Initializes the sound driver.
+ DRESULT (*InitSound)( InitSoundInfo *pSoundInfo );
+
+ // Volume controls between 0 - 100
+ unsigned short ( *GetSoundVolume )();
+ void ( *SetSoundVolume )( unsigned short nVolume );
+
+ // Controls the reverb properties.
+ // Inputs:
+ DRESULT ( *SetReverbProperties )( ReverbProperties *pReverbProperties );
+ DRESULT ( *GetReverbProperties )( ReverbProperties *pReverbProperties );
+
+ // These PlaySound function allows the client shell to initiate and control sounds
+ // without going through the server. These sounds will only be played
+ // on the client initiating them. These functions will fill m_hSound
+ // with the handle to the client sound if you set the PLAYSOUND_GETHANDLE flag. This will
+ // also force the sound not to be automatically deleted when the sound is done playing. You
+ // must call KillSound. You must get the handle in order to use the other sound functions
+ // like SetSoundPosition.
+
+ // Play a sound with full control
+ // Arguments:
+ // pPlaySoundInfo - sound control structure
+ // Return:
+ // Handle to the client only sound.
+ DRESULT (*PlaySound)( PlaySoundInfo *pPlaySoundInfo );
+
+ // Update position and orientation of a client only sound.
+ // Arguments:
+ // hSound - Handle to client only sound.
+ // pPos - New position of sound. Can be NULL.
+ // Return:
+ // LT_OK - Successful.
+ // LT_INVALIDPARAM - Invalid parameters.
+ // LT_ERROR - Unable find hSound
+ DRESULT (*SetSoundPosition)( HSOUNDDE hSound, DVector *pPos );
+
+ // Get current position and orientation of a client only sound.
+ // Arguments:
+ // hSound - Handle to client only sound.
+ // pPos - Destination of position. Can be NULL.
+ // pOrientation - Destination of orientation. Can be NULL.
+ // Return:
+ // LT_OK - Successful.
+ // LT_INVALIDPARAM - Invalid parameters.
+ // LT_ERROR - Unable to find hSound.
+ DRESULT (*GetSoundPosition)( HSOUNDDE hSound, DVector *pPos );
+
+ // Pause/resume sounds.
+ void (*PauseSounds)( );
+ void (*ResumeSounds)( );
+
+ // Get total length in seconds of sound.
+ // Arguments:
+ // hSound - Handle to sound.
+ // fDuration - Duration of sound.
+ // Returns:
+ // DE_OK if successful.
+ // DE_INVALIDPARAMS if hSound not available.
+ DRESULT (*GetSoundDuration)( HSOUNDDE hSound, DFLOAT *fDuration );
+
+ // Check if sound finished playing or if object it was attached to was removed.
+ // Arguments:
+ // pSoundHandle - handle to client only sound
+ DBOOL (*IsDone)( HSOUNDDE pSoundHandle );
+
+ // Kill a sound.
+ // Arguments:
+ // pSoundHandle - handle to client only sound
+ void (*KillSound)( HSOUNDDE pSoundHandle );
+
+ // Set the listener status, position and orientation. If bListenerInClient is TRUE, then
+ // pPos and pRot are ignored and can be set to NULL.
+ void (*SetListener)( DBOOL bListenerInClient, DVector *pPos, DRotation *pRot );
+
+
+ // Video functions. These functions use Smacker movies.
+
+ // DE_OK, VIDEO_ERROR.
+ // flags is a combination of the PLAYBACK_ flags in de_codes.h.
+ DRESULT (*StartVideo)(char *pFilename, DDWORD flags);
+ DRESULT (*StopVideo)();
+
+ // Draws the current video playback to the screen.
+ DRESULT (*UpdateVideo)();
+
+ // VIDEO_PLAYING, VIDEO_NOTPLAYING.
+ DRESULT (*IsVideoPlaying)();
+
+
+ // String functions. Strings are reference counted objects that cannot
+ // be manipulated. When you create one with FormatString or CreateString,
+ // the reference count is 1. When you copy a string with CopyString, the
+ // reference count is incremented. When you free one with FreeString,
+ // it decrements the reference count.. when the reference count goes to
+ // zero, it deletes the string. If you forget to free up any strings,
+ // DirectEngine will spit out a message telling you about it..
+
+ // In Windows, messageCode comes from your resource DLL. The messages
+ // need to be formatted with %1!s! %2!s! (the number is the argument
+ // number and the !s! says its a string). You can also use !f! and !d!
+ // for floating point and whole number.
+ HSTRING (*FormatString)(int messageCode, ...);
+
+ // Copy a string.. much more efficient than CreateString().
+ HSTRING (*CopyString)(HSTRING hString);
+ HSTRING (*CreateString)(char *pString);
+ void (*FreeString)(HSTRING hString);
+
+ DBOOL (*CompareStrings)(HSTRING hString1, HSTRING hString2);
+ DBOOL (*CompareStringsUpper)(HSTRING hString1, HSTRING hString2);
+
+ // Get the string's data.. you really should only use this for strings
+ // that you stored off and want to pass to the engine for a filename
+ // or something.. Most strings could be in some format other than ANSI.
+ char* (*GetStringData)(HSTRING hString);
+
+
+ // Intersections.
+
+ // Intersect a line segment.. (used to be raycast, but line segments are WAY faster).
+ // Returns TRUE and fills in pInfo if it hit something.
+ DBOOL (*IntersectSegment)(ClientIntersectQuery *pQuery, ClientIntersectInfo *pInfo);
+
+ // Same as IntersectSegment, except for it casts a ray from pQuery->m_From
+ // in the direction of pQuery->m_Dir.
+ DBOOL (*CastRay)(ClientIntersectQuery *pQuery, ClientIntersectInfo *pInfo);
+
+ // Find objects in a sphere. This is only based on their centerpoints, not
+ // on their dimensions or anything. inObjects is filled in and nOutObjects
+ // is set to the number of objects filled in. nFound might be larger if
+ // it found more objects than nInObjects.
+ DRESULT (*FindObjectsInSphere)(DVector *pCenter, float radius,
+ HLOCALOBJ *inObjects, DDWORD nInObjects, DDWORD *nOutObjects, DDWORD *nFound);
+
+
+ // Fonts..
+
+ // Creates the closest font it can to the one you asked for.
+ HDEFONT (*CreateFont)(char *pFontName, int width, int height,
+ DBOOL bItalic, DBOOL bUnderline, DBOOL bBold);
+
+ void (*DeleteFont)(HDEFONT hFont);
+
+
+ // Colors..
+
+ // r, g, and b go from 0 to 1.
+ // bTransparent is only used when the function specifies so.
+ // Note: anywhere you can pass a color, if you pass in NULL, it'll use black.
+ HDECOLOR (*CreateColor)(float r, float g, float b, DBOOL bTransparent);
+ void (*DeleteColor)(HDECOLOR hColor);
+
+ // Just for convenience. You don't have to create/delete these colors,
+ // and they're always around!
+ HDECOLOR (*SetupColor1)(float r, float g, float b, DBOOL bTransparent);
+ HDECOLOR (*SetupColor2)(float r, float g, float b, DBOOL bTransparent);
+
+
+ // Surface management.
+ // Note: All the rectangles you specify in here do not include the right and bottom
+ // edges. ie: If you draw a rectangle (0, 1, 0, 1), it'll draw 1 pixel
+ // instead of 4 pixels.
+
+ // Note: Try to use the screen surface as little as possible. Using the screen
+ // surface stalls ALL asynchronous rendering performance and can cut framerate
+ // in half on some cards. That's not to say don't use them in the interface,
+ // just don't use them for things that are always there like frag counts, etc..
+ // The only functions that don't stall async performance (feel free to use
+ // these regularly) are:
+ // DrawSurfaceToSurface
+ // DrawSurfaceToSurfaceTransparent
+ // ScaleSurfaceToSurface
+ // ScaleSurfaceToSurfaceTransparent
+
+ // This goes around the edges of the surface and returns the smallest inside
+ // rectangle allowing for a border of hColor. For example, if hSurface
+ // had a black border of 2 pixels on the left and right and a black border
+ // of 3 pixels on the top and bottom, pRect would be set to (2,3,2,3).
+ DRESULT (*GetBorderSize)(HSURFACE hSurface, HDECOLOR hColor, DRect *pRect);
+
+ // Any surfaces you use while rendering 3D stuff at the same time should be optimized
+ // with this function and drawn in an StartOptimized2D/EndOptimized2D block.
+ // You need to call OptimizeSurface each time you change its contents.
+ DRESULT (*OptimizeSurface)(HSURFACE hSurface, HDECOLOR hTransparentColor);
+ DRESULT (*UnoptimizeSurface)(HSURFACE hSurface);
+
+ HSURFACE (*GetScreenSurface)();
+
+ // Creates a surface sized to the dimensions of the bitmap.
+ // The bitmap is an 8-bit (you can use any palette you want..) PCX file.
+ // So pBitmapName might look like "interface/bitmaps/menu1.pcx".
+ HSURFACE (*CreateSurfaceFromBitmap)(char *pBitmapName);
+
+ // Creates a surface just large enough for the string.
+ // You can make the surface a little larger with extraPixelsX and extraPixelsY.
+ HSURFACE (*CreateSurfaceFromString)(HDEFONT hFont, HSTRING hString,
+ HDECOLOR hForeColor, HDECOLOR hBackColor,
+ int extraPixelsX, int extraPixelsY);
+
+ // Create a plain old surface.
+ HSURFACE (*CreateSurface)(DDWORD width, DDWORD height);
+
+ DRESULT (*DeleteSurface)(HSURFACE hSurface);
+
+ // Attach whatever user data you want to a surface.
+ void* (*GetSurfaceUserData)(HSURFACE hSurface);
+ void (*SetSurfaceUserData)(HSURFACE hSurface, void *pUserData);
+
+ // Access the pixels (SLOW).
+ DRESULT (*GetPixel)(HSURFACE hSurface, DDWORD x, DDWORD y, HDECOLOR *color);
+ DRESULT (*SetPixel)(HSURFACE hSurface, DDWORD x, DDWORD y, HDECOLOR color);
+
+ // Gets the dimensions that this string would take up.
+ void (*GetStringDimensions)(HDEFONT hFont, HSTRING hString, int *sizeX, int *sizeY);
+
+ // Draws the string into the rectangle..
+ void (*DrawStringToSurface)(HSURFACE hDest, HDEFONT hFont, HSTRING hString,
+ DRect *pRect, HDECOLOR hForeColor, HDECOLOR hBackColor);
+
+ // You can pass in NULL for pWidth and pHeight if you want.
+ void (*GetSurfaceDims)(HSURFACE hSurf, DDWORD *pWidth, DDWORD *pHeight);
+
+ // Draw a bitmap to a surface..
+ DBOOL (*DrawBitmapToSurface)(HSURFACE hDest, char *pSourceBitmapName,
+ DRect *pSrcRect, int destX, int destY);
+
+ // Draws hSrc to hDest like a normal transparent blit, but tiles hMask's surface
+ // into the nontransparent pixels of hSrc (can you say airbrushed text?)
+ // You can't have a mask texture larger than 256x256, and the mask must be
+ // a power of 2.
+ DRESULT (*DrawSurfaceMasked)(HSURFACE hDest, HSURFACE hSrc, HSURFACE hMask,
+ DRect *pSrcRect, int destX, int destY, HDECOLOR hColor);
+
+ // Draws hSrc onto hDest, but fills in the nontransparent pixels with the
+ // color you specify.
+ DRESULT (*DrawSurfaceSolidColor)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pSrcRect, int destX, int destY, HDECOLOR hTransColor, HDECOLOR hFillColor);
+
+ // Draws the source surface onto the dest surface. You can specify a rectangle
+ // in the source surface and the destination coordinates on the destination
+ // surface.. it doesn't scale the bitmap.. If you pass in NULL for the source
+ // rect, it'll just use the whole thing.
+ DRESULT (*DrawSurfaceToSurface)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pSrcRect, int destX, int destY);
+
+ DRESULT (*DrawSurfaceToSurfaceTransparent)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pSrcRect, int destX, int destY, HDECOLOR hColor);
+
+ // Scales the source surface rectangle into the dest rectangle..
+ DRESULT (*ScaleSurfaceToSurface)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pDestRect, DRect *pSrcRect);
+
+ DRESULT (*ScaleSurfaceToSurfaceTransparent)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pDestRect, DRect *pSrcRect, HDECOLOR hColor);
+
+ DRESULT (*ScaleSurfaceToSurfaceSolidColor)(HSURFACE hDest, HSURFACE hSrc,
+ DRect *pDestRect, DRect *pSrcRect, HDECOLOR hTransColor, HDECOLOR hFillColor);
+
+ // (Affine) warps the source poly into the dest poly. The source
+ // coordinates are CLAMPED to be inside the source surface's rectangle, and
+ // the warp is clipped against the destination rectangle (ie: don't specify
+ // coordinates outside the source rectangle, but feel free to specify them
+ // outside the destination rectangle). The polygon you specify should be
+ // convex. The minimum number of coordinates is 3 and the maximum
+ // is 10.
+ DRESULT (*WarpSurfaceToSurface)(HSURFACE hDest, HSURFACE hSrc,
+ DWarpPt *pCoords, int nCoords);
+
+ DRESULT (*WarpSurfaceToSurfaceTransparent)(HSURFACE hDest, HSURFACE hSrc,
+ DWarpPt *pCoords, int nCoords, HDECOLOR hColor);
+
+ DRESULT (*WarpSurfaceToSurfaceSolidColor)(HSURFACE hDest, HSURFACE hSrc,
+ DWarpPt *pCoords, int nCoords, HDECOLOR hTransColor, HDECOLOR hFillColor);
+
+ // Transform the source surface onto the dest surface. The origin is
+ // in the destination surface's coordinates. If you specify NULL, it will
+ // use the centerpoint as the origin.
+ DRESULT (*TransformSurfaceToSurface)(HSURFACE hDest, HSURFACE hSrc,
+ DFloatPt *pOrigin, int destX, int destY, float angle,
+ float scaleX, float scaleY);
+
+ DRESULT (*TransformSurfaceToSurfaceTransparent)(HSURFACE hDest, HSURFACE hSrc,
+ DFloatPt *pOrigin, int destX, int destY, float angle,
+ float scaleX, float scaleY, HDECOLOR hColor);
+
+ // Draw a filled rectangle into the surface.
+ DRESULT (*FillRect)(HSURFACE hDest, DRect *pRect, HDECOLOR hColor);
+
+
+
+ // Access to client console variables...
+
+ // Register a console program. pName is just stored so it should either be
+ // static or allocated. When the client shell DLL is unloaded, it gets
+ // rid of any registered programs.
+ // Returns DE_OK or DE_ALREADYEXISTS.
+ DRESULT (*RegisterConsoleProgram)(char *pName, ConsoleProgramFn fn);
+
+ // Returns DE_OK or DE_NOTFOUND.
+ DRESULT (*UnregisterConsoleProgram)(char *pName);
+
+ // Returns NULL if the parameter doesn't exist.
+ HCONSOLEVAR (*GetConsoleVar)(char *pName);
+
+ // Gets the value of a parameter .. returns 0/NULL if you pass in NULL.
+ float (*GetVarValueFloat)(HCONSOLEVAR hVar);
+ char* (*GetVarValueString)(HCONSOLEVAR hVar);
+
+ // Access to server console mirror variables...
+
+ // The 'new' accessors for server console variables. Returns DE_NOTFOUND
+ // if the variable isn't found.
+ virtual DRESULT GetSConValueFloat(char *pName, float &val)=0;
+ virtual DRESULT GetSConValueString(char *pName, char *valBuf, DDWORD bufLen)=0;
+
+ // Gets the value of a parameter .. returns 0/NULL if you pass in NULL.
+ // OBSOLETE (will be removed soon). Use the GetSCon functions.
+ virtual float GetServerConVarValueFloat(char *pName)=0;
+ virtual char* GetServerConVarValueString(char *pName)=0;
+
+
+ // Helpers..
+
+ // Use these to time sections of code. Timing is done in microseconds
+ // (1,000,000 counts per second).
+ void (*StartCounter)(struct DCounter_t *pCounter);
+ DDWORD (*EndCounter)(struct DCounter_t *pCounter);
+
+ // Setup the panning sky stuff. Pass in DNULL for the filename if you want
+ // to disable the panning sky. Returns DE_NOTFOUND if it can't find
+ // the texture.
+ // index tells which global panning thing you want to change. It
+ // is one of the GLOBALPAN_ defines in de_codes.h.
+ DRESULT (*SetGlobalPanTexture)(DDWORD index, char *pFilename);
+ DRESULT (*SetGlobalPanInfo)(DDWORD index, float xOffset, float zOffset, float xScale, float zScale);
+
+ // Register a surface effect. You should register all your effects in OnEngineInitialized
+ // (before you start a world).
+ DRESULT (*AddSurfaceEffect)(SurfaceEffectDesc *pDesc);
+
+ // Turn the input state on or off. This is for times when the client
+ // is interacting with menus and you don't want their mouse movement or
+ // keystrokes to get sent to the server. This defaults to ON.
+ void (*SetInputState)(DBOOL bOn);
+
+ // Clears all the keyboard, command, and axis offset input.
+ DRESULT (*ClearInput)();
+
+ // Returns a list of DeviceBindings for a given device. You must call FreeDeviceBindings()
+ // to free the list.
+ DeviceBinding* (*GetDeviceBindings)(DDWORD nDevice);
+ void (*FreeDeviceBindings)(DeviceBinding* pBindings);
+
+ // Track Input Devices. Between calls to StartDeviceTrack() and EndDeviceTrack() no command
+ // states will be set through the normal input. Pass in the devices to track (DEVICETYPE_
+ // defines) and a buffer size for all input devices. The buffer size is the number of events
+ // that could occur between calls to TrackDevice(), not to exceed MAX_INPUT_BUFFER_SIZE.
+ // Supply TrackDevice() with an array of DeviceInput structures, and the number of structures
+ // in the array. When TrackDevice() returns, the pnInOut variable will contain the number of
+ // events that have occurred (the number of filled-in DeviceInput structures). If there were
+ // more events that occurred than the original buffer size allowed for, TrackDevice will return
+ // LT_INPUTBUFFEROVERFLOW.
+ DRESULT (*StartDeviceTrack)(DDWORD nDevices, DDWORD nBufferSize);
+ DRESULT (*TrackDevice)(DeviceInput* pInputArray, DDWORD* pnInOut);
+ DRESULT (*EndDeviceTrack)();
+
+ // Retrieve a list of device objects (like axes, buttons, etc.) for one or more devices.
+ // Pass GetDeviceObjects a combination of DEVICETYPE_ flags and it will return a DeviceObject
+ // (defined in basedefs_de.h) list.
+ // You must free the list with FreeDeviceObjects().
+ DeviceObject* (*GetDeviceObjects)(DDWORD nDeviceFlags);
+ void (*FreeDeviceObjects)(DeviceObject* pList);
+
+ // Get the name of the first input device of the given type.
+ // Returns either LT_OK or DE_NOTFOUND.
+ DRESULT (*GetDeviceName)(DDWORD nDeviceType, char* pStrBuffer, DDWORD nBufferSize);
+
+ // Find out if the specified device is enabled yet.
+ // Fills in the BOOL pointer and always returns LT_OK.
+ DRESULT (*IsDeviceEnabled)(char* strDeviceName, DBOOL* pIsEnabled);
+
+ // Attempt to enable specified device.
+ // Returns LT_OK or LT_ERROR.
+ DRESULT (*EnableDevice)(char* strDeviceName);
+
+ // These access the real, accurate timer.
+ float (*GetTime)();
+ float (*GetFrameTime)();
+
+
+ // These access the GAME timer (which resides on the server).
+ // Since this comes from the server, it will be intermittent, so only
+ // use it for things that must be synced with server. This timer will
+ // not update when there isn't a connection to the server.
+ float (*GetGameTime)();
+ float (*GetGameFrameTime)();
+
+
+ // Print a string to the console.
+ void (*CPrint)(char *pMsg, ...);
+
+ // Used to output a TRACE message to the Debug Output window. Newlines must be explicitly used.
+ void (*DebugOut)( char *pMsg, ... );
+
+ DBOOL (*IsCommandOn)(int commandNum);
+
+ // Same as typing a string into the console.
+ void (*RunConsoleString)(char *pString);
+
+ // Gives you a pointer to the client shell you created.
+ LPCLIENTSHELLDE (*GetClientShell)();
+
+ // Get your client object (NULL if you don't currently have one).
+ HLOCALOBJ (*GetClientObject)();
+
+ // Rotate a rotation around the given vector.
+ void (*RotateAroundAxis)(DRotation *pRotation, DVector *pAxis, float amount);
+
+ // Treat the rotation like Euler angles...
+ void (*EulerRotateX)(DRotation *pRotation, float amount);
+ void (*EulerRotateY)(DRotation *pRotation, float amount);
+ void (*EulerRotateZ)(DRotation *pRotation, float amount);
+
+ // Align a rotation to a normal. The vector you pass in becomes the
+ // forward vector in the rotation it outputs.
+ // Use pUp to set the frame of reference or set it to NULL, in which case
+ // the up vector could be anything. pUp should not be equal to pVector.
+ void (*AlignRotation)(DRotation *pRotation, DVector *pVector, DVector *pUp);
+
+ // OBSOLETE: use CommonLT::SetupEuler.
+ virtual DRESULT SetupEuler(DRotation *pRotation, float pitch, float yaw, float roll)=0;
+
+ // Interpolate between two rotations (with quaternions).
+ DRESULT (*InterpolateRotation)(DRotation *pDest, DRotation *pRot1, DRotation *pRot2, float t);
+
+ // OBSOLETE. Use CommonLT::GetRotationVectors.
+ virtual DRESULT GetRotationVectors(DRotation *pRotation, DVector *pUp, DVector *pRight, DVector *pForward)=0;
+
+
+ // You can set a global light scale that's applied to all rendering.
+ // Colors are RGB 0-1 (values are clamped for you).
+ void (*GetGlobalLightScale)(DVector *pScale);
+ void (*SetGlobalLightScale)(DVector *pScale);
+ void (*OffsetGlobalLightScale)(DVector *pOffset);
+
+ // Obsolete, use Parse2.
+ int (*Parse)(char *pCommand, char **pNewCommandPos, char *argBuffer, char **argPointers, int *nArgs);
+
+
+
+ // Messaging.
+
+ virtual HMESSAGEWRITE StartMessage(DBYTE messageID)=0;
+ virtual DRESULT EndMessage(HMESSAGEWRITE hMessage)=0; // Just calls EndMessage2 with MESSAGE_GUARANTEED.
+ virtual DRESULT EndMessage2(HMESSAGEWRITE hMessage, DDWORD flags)=0;
+
+
+ // NEW message functions. These functions don't free the message so you need to
+ // call LMessage::Release after sending.
+
+ virtual DRESULT SendToServer(LMessage &msg, DBYTE msgID, DDWORD flags)=0;
+
+
+ // Management of client-side objects.
+
+ HLOCALOBJ (*CreateObject)(ObjectCreateStruct *pStruct);
+ DRESULT (*DeleteObject)(HLOCALOBJ hObj);
+
+ // Gets the objects attached to this object. outListSize is filled in with how many
+ // objects it filled into inList and outNumAttachment is the actual number of attachments
+ // (which can be larger than outListSize if inListSize is too small to fit them all).
+ DRESULT (*GetAttachments)(HLOCALOBJ hObj, HLOCALOBJ *inList, DDWORD inListSize,
+ DDWORD *outListSize, DDWORD *outNumAttachments);
+
+ // Updates the position/rotation of the attachments on the object. Attachments are
+ // always automatically updated when the object is rendered.
+ virtual DRESULT ProcessAttachments(HOBJECT hObj)=0;
+
+
+ // Change position and rotation. It's more efficient to set them
+ // at the same time...
+ void (*GetObjectPos)(HLOCALOBJ hObj, DVector *pPos);
+ void (*SetObjectPos)(HLOCALOBJ hObj, DVector *pPos);
+
+ void (*GetObjectRotation)(HLOCALOBJ hObj, DRotation *pRotation);
+ void (*SetObjectRotation)(HLOCALOBJ hObj, DRotation *pRotation);
+ void (*SetObjectPosAndRotation)(HLOCALOBJ hObj, DVector *pPos, DRotation *pRotation);
+
+ DDWORD (*GetObjectType)(HLOCALOBJ hObj);
+
+ // Get/Set scale.
+ DRESULT (*GetObjectScale)(HLOCALOBJ hObj, DVector *pScale);
+ DRESULT (*SetObjectScale)(HLOCALOBJ hObj, DVector *pScale);
+
+ // RGB 0-1.
+ void (*GetObjectColor)(HLOCALOBJ hObject, float *r, float *g, float *b, float *a);
+ void (*SetObjectColor)(HLOCALOBJ hObject, float r, float g, float b, float a);
+
+ DDWORD (*GetObjectFlags)(HLOCALOBJ hObj);
+ void (*SetObjectFlags)(HLOCALOBJ hObj, DDWORD flags);
+
+ // Get/Set object user flags. Can't set user flags on an object
+ // created on the server.
+ DRESULT (*GetObjectUserFlags)(HLOCALOBJ hObj, DDWORD *pFlags);
+ DRESULT (*SetObjectUserFlags)(HLOCALOBJ hObj, DDWORD flags);
+
+ // Get/set the client flags (defined above).
+ DDWORD (*GetObjectClientFlags)(HLOCALOBJ hObj);
+ void (*SetObjectClientFlags)(HLOCALOBJ hObj, DDWORD flags);
+
+ // User data for the object..
+ void* (*GetObjectUserData)(HLOCALOBJ hObj);
+ void (*SetObjectUserData)(HLOCALOBJ hObj, void *pData);
+
+
+ // Camera functions.
+
+ // Gets the 3D coordinates of a screen coordinate given a camera. The 3D
+ // coordinate is one unit out along the forward vector. Returns DE_OUTSIDE
+ // if the screen coordinates aren't inside the camera's rectangle.
+ DRESULT (*Get3DCameraPt)(HLOCALOBJ hCamera, int sx, int sy, DVector *pOut);
+
+ // Get/Set a camera's FOV. It defaults to (PI/2, PI/2).
+ // It will clamp your values between (PI/100, 99*PI/100)
+ void (*GetCameraFOV)(HLOCALOBJ hObj, float *pX, float *pY);
+ void (*SetCameraFOV)(HLOCALOBJ hObj, float fovX, float fovY);
+
+ void (*GetCameraRect)(HLOCALOBJ hObj, DBOOL *bFullscreen,
+ int *left, int *top, int *right, int *bottom);
+
+ // Set the camera's rectangle on the screen.
+ // If bFullscreen is DTRUE, then it ignores the rect and draws the
+ // camera fullscreen. If the rectangle extends over the screen
+ // boundaries, then it is clipped..
+ void (*SetCameraRect)(HLOCALOBJ hObj, DBOOL bFullscreen,
+ int left, int top, int right, int bottom);
+
+ // Get/Set the camera light add. RGB 0-1. Light add is applied AFTER
+ // scaling, so if light is fully bright and scaling is zero, you'll just
+ // see whiteness. When the light add is nonzero, it draws a poly over
+ // the screen so don't use it all the time!
+ // These return DFALSE if the object is not a camera.
+ DBOOL (*GetCameraLightAdd)(HLOCALOBJ hCamera, DVector *pAdd);
+ DBOOL (*SetCameraLightAdd)(HLOCALOBJ hCamera, DVector *pAdd);
+
+
+
+ // Particle system manipulation.
+
+ // gravityAccel default is -500
+ // flags default is 0
+ // particleRadius default is 300
+ // color scale defauls to 1.0
+ // Particle colors are 0-255.
+
+ // All particle positions are RELATIVE to the particle system's
+ // position and rotation. In many cases, you can have your code be very simple
+ // and fast if you just move and rotate the particle system and not the particles.
+
+ // Change the system's parameters.
+ DRESULT (*SetupParticleSystem)(HLOCALOBJ hObj, char *pTextureName, float gravityAccel, DDWORD flags, float particleRadius);
+
+ // The software version uses a single color for all the particles in each
+ // system specified here (default 1). RGB (0-1).
+ DRESULT (*SetSoftwarePSColor)(HLOCALOBJ hObj, float r, float g, float b);
+
+ virtual DEParticle* AddParticle(HLOCALOBJ hObj, DVector *pPos, DVector *pVelocity, DVector *pColor, float lifeTime)=0;
+
+ void (*AddParticles)(HLOCALOBJ hObj, DDWORD nParticles,
+ DVector *pMinOffset, DVector *pMaxOffset,
+ DVector *pMinVelocity, DVector *pMaxVelocity,
+ DVector *pMinColor, DVector *pMaxColor,
+ float minLifetime, float maxLifetime);
+
+ DBOOL (*GetParticles)(HLOCALOBJ hObj, DEParticle **pHead, DEParticle **pTail);
+
+ // Get/Set particle positions. hSystem is NOT checked to be valid here
+ // for speed so make sure it's valid!
+ void (*GetParticlePos)(HLOCALOBJ hSystem, DEParticle *pParticle, DVector *pPos);
+ void (*SetParticlePos)(HLOCALOBJ hSystem, DEParticle *pParticle, DVector *pPos);
+
+ // Remove a particle.
+ void (*RemoveParticle)(HLOCALOBJ hSystem, DEParticle *pParticle);
+
+ // This is an optimization you can make to help the engine minimize its boundaries on
+ // a particle system. If you create particles in various places and they go away, you
+ // can use this every so often to recalculate where the particles are.
+ DRESULT (*OptimizeParticles)(HLOCALOBJ hSystem);
+
+
+
+ // Line system manipulation.
+ // As with particle systems, the lines are centered around the object's origin.
+ // Don't just place the object at the origin and put lines way off to the side,
+ // it's more efficient to keep the lines as close to the center as possible.
+
+ // Set hPrev to NULL to start, then pass in the return value, etc..
+ // Returns DNULL for last line.
+ // ** If you call RemoveLine on the current HDELINE, DO NOT
+ // ** pass that into GetNextLine - call GetNextLine first
+ // ** while the HDELINE is still valid!
+ HDELINE (*GetNextLine)(HLOCALOBJ hObj, HDELINE hPrev);
+
+ void (*GetLineInfo)(HDELINE hLine, DELine *pLine);
+ void (*SetLineInfo)(HDELINE hLine, DELine *pLine);
+
+ // Adds a line to the end of the line system's list.
+ HDELINE (*AddLine)(HLOCALOBJ hObj, DELine *pLine);
+ void (*RemoveLine)(HLOCALOBJ hObj, HDELINE hLine);
+
+
+ // Poly grid manipulation.
+
+ // A poly grid is basically a heightmapped grid of pixels that are drawn
+ // as polygons. Each pixel can have a value from -127 to 127. The pixel's value
+ // defines its height and is a lookup into the color table for the vertex color.
+ // You can scale and rotate the poly grid using SetObjectScale and SetObjectRotation.
+ // bHalfTriangles will cause it to look VERY triangulated, but draw way faster.
+ DBOOL (*SetupPolyGrid)(HLOCALOBJ hObj, DDWORD width, DDWORD height, DBOOL bHalfTrianges);
+
+ // Set the texture. The texture MUST be a sprite file. It CANNOT be a .dtx file!
+ DRESULT (*SetPolyGridTexture)(HLOCALOBJ hObj, char *pFilename);
+
+ // Set the environment map for the PolyGrid. This MUST be a DTX file.
+ // Specify NULL if you want to disable the environment map. Returns
+ // DE_NOTFOUND if it can't find the specified map.
+ DRESULT (*SetPolyGridEnvMap)(HLOCALOBJ hObj, char *pFilename);
+
+ // Get/Set the texture pan and scale for a PolyGrid.
+ // Defaults are 0.0 for xPan and yPan, and 1.0 for xScale and yScale.
+ DRESULT (*GetPolyGridTextureInfo)(HLOCALOBJ hObj, float *xPan, float *yPan, float *xScale, float *yScale);
+ DRESULT (*SetPolyGridTextureInfo)(HLOCALOBJ hObj, float xPan, float yPan, float xScale, float yScale);
+
+ // You can set it to be transparent or not. It defaults to not being transparent.
+ DRESULT (*GetPolyGridInfo)(HLOCALOBJ hObj, char **pBytes, DDWORD *pWidth, DDWORD *pHeight, PGColor **pColorTable);
+
+ // Set pMin and pMax to the dimensions of the box you want the polygrid to fit in.
+ // pPos and pScale will be filled in with the recommended position and scale.
+ DRESULT (*FitPolyGrid)(HLOCALOBJ hObj, DVector *pMin, DVector *pMax, DVector *pPos, DVector *pScale);
+
+
+ // Light manipulation.
+
+ // Get/Set a light's color (RGB, 0.0f to 1.0f).
+ // When you create a light, its color defaults to (0,0,0).
+ void (*GetLightColor)(HLOCALOBJ hObj, float *r, float *g, float *b);
+ void (*SetLightColor)(HLOCALOBJ hObj, float r, float g, float b);
+
+ // Get/Set a light's radius.
+ // When you create a light, its radius defaults to 100.
+ float (*GetLightRadius)(HLOCALOBJ hObj);
+ void (*SetLightRadius)(HLOCALOBJ hObj, float radius);
+
+
+ // Container manipulation.
+
+ // Get a container's code.
+ // Returns DFALSE if the object is not a container.
+ DBOOL (*GetContainerCode)(HLOCALOBJ hObj, D_WORD *pCode);
+
+ // Find out what containers contain the given point.
+ // Returns the number of containers filled in.
+ DDWORD (*GetPointContainers)(DVector *pPoint, HLOCALOBJ *pList, DDWORD maxListSize);
+
+
+ // Sprite manipulation.
+
+ // This clips the sprite on the poly.
+ // Returns DE_OK or DE_ERROR if not a sprite.
+ // Pass in INVALID_HPOLY to un-clip the sprite.
+ DRESULT (*ClipSprite)(HLOCALOBJ hObj, HPOLY hPoly);
+
+ // Get the sprite control interface for a sprite. Returns DE_INVALIDPARAMS
+ // if the object is not a sprite.
+ virtual DRESULT GetSpriteControl(HLOCALOBJ hObj, SpriteControl* &pControl)=0;
+
+
+ // Client-side models..
+
+ // Iterate through the model's nodes. Returns DE_FINISHED when there are no more.
+ // hCurNode = INVALID_MODEL_NODE;
+ // while(interface->GetNextModelNode(hModel, hCurNode, &hCurNode) == DE_OK)
+ // { ... }
+ DRESULT (*GetNextModelNode)(HLOCALOBJ hObject, HMODELNODE hNode, HMODELNODE *pNext);
+
+ // Get a model node's name.
+ DRESULT (*GetModelNodeName)(HLOCALOBJ hObject, HMODELNODE hNode, char *pName, DDWORD maxLen);
+
+ // Hide/unhide a node on the model (they're all unhidden by default).
+ // Returns DE_OK, DE_ERROR, LT_NOCHANGE, or DE_NODENOTFOUND.
+ DRESULT (*GetModelNodeHideStatus)(HOBJECT hObj, char *pNodeName, /* out */DBOOL *bHidden);
+ DRESULT (*SetModelNodeHideStatus)(HOBJECT hObj, char *pNodeName, DBOOL bHidden);
+
+ // Get the current (global) transformation for a model node.
+ // Returns DFALSE if the node does not exist or if the object
+ // you pass in is not a model.
+ DBOOL (*GetModelNodeTransform)(HOBJECT hObj, char *pNodeName,
+ DVector *pPos, DRotation *pRot);
+
+ // Returns the animation the model is currently on. (DDWORD)-1 if none.
+ DDWORD (*GetModelAnimation)(HLOCALOBJ hObj);
+ void (*SetModelAnimation)(HLOCALOBJ hObj, DDWORD iAnim);
+
+ // Get an animation index from a model.
+ // Returns -1 if the animation doesn't exist (or if the object isn't a model).
+ HMODELANIM (*GetAnimIndex)(HOBJECT hObj, char *pAnimName);
+
+ // Starts the current animation over.
+ DRESULT (*ResetModelAnimation)(HLOCALOBJ hObj);
+
+ // Tells what the playback state of the model is (a combination of the
+ // MS_ bits defined in basedefs_de.h).
+ DDWORD (*GetModelPlaybackState)(HLOCALOBJ hObj);
+
+ // Get/Set the looping state of the model. The default state is TRUE.
+ DBOOL (*GetModelLooping)(HLOCALOBJ hObj);
+ void (*SetModelLooping)(HLOCALOBJ hObj, DBOOL bLoop);
+
+
+ // (Geometry) surface functions.
+
+ DBOOL (*GetSurfaceBounds)(SurfaceData *pSurface, DVector *pMin, DVector *pMax);
+
+ // Hide/Unhide a poly.
+ DRESULT (*SetPolyHideStatus)(HPOLY hPoly, DBOOL bHide);
+
+ // Just used for internal debugging.. never use this.
+ DRESULT (*GetPolyIndex)(HPOLY hPoly, DDWORD *pIndex);
+
+ // Get the texture flags from a poly. Returns DE_OK
+ // or DE_ERROR if no world is loaded or hPoly is invalid.
+ DRESULT (*GetPolyTextureFlags)(HPOLY hPoly, DDWORD *pFlags);
+
+
+ // Render hooks.
+
+ // When this is set, the renderer will call your hook function before drawing each
+ // model. Either keep the function very fast or set it to NULL so you don't slow
+ // the renderer down.
+ DRESULT (*SetModelHook)(ModelHookFn fn, void *pUser);
+
+
+ // Engine hooks.
+
+ // This is here so we can avoid adding API functions if necessary and for
+ // some system-dependent or misc. stuff. Pass in a string describing what
+ // you want and it fills in pData.
+ // Returns DE_OK if it understands the string or an error otherwise.
+ // Strings:
+ // HWND: Returns main window handle.
+ DRESULT (*GetEngineHook)(char *pName, void **pData);
+
+
+ // Network startup/join/host functions.
+
+ // Call this function before calling any other
+ // network functions. pDriver can be NULL to use the default net driver.
+ // No flags are currently supported.
+ DRESULT (*InitNetworking)(char *pDriver, DDWORD dwFlags);
+
+ // Gets a list of net services (tcp/ip, modem, etc).
+ DRESULT (*GetServiceList)(NetService* &pListHead);
+
+ // Call this function when you are finished using the list returned by
+ // GetServiceList().
+ DRESULT (*FreeServiceList)(NetService *pListHead);
+
+ // Selects the given service as the one to use.
+ DRESULT (*SelectService)(HNETSERVICE hNetService);
+
+ // Gets a list (and count) of enumerated sessions.
+ // See driver flags for a description of pInfo.
+ DRESULT (*GetSessionList)(NetSession* &pListHead, char *pInfo);
+
+ // Call this function when you are finished using the list returned by
+ // GetSessionList().
+ DRESULT (*FreeSessionList)(NetSession *pListHead);
+
+
+ // Alternate mode of getting session lists. These only work for services with
+ // the NETSERVICE_TCPIP flag. These functions return immediately so you can update
+ // a UI in the background without having to 'freeze' the UI while it queries hosts.
+
+ // Start querying. pInfo contains the address list formatted just like GetSessionLists.
+ virtual DRESULT StartQuery(char *pInfo)=0;
+
+ // Update the query. Call this as often as possible.
+ virtual DRESULT UpdateQuery()=0;
+
+ // Get the current list of results from the query. Each time you call this,
+ // a new session list is allocated and you need to free it with FreeSessionList.
+ virtual DRESULT GetQueryResults(NetSession* &pListHead)=0;
+
+ // End the current query.
+ virtual DRESULT EndQuery()=0;
+
+
+ // Determines if we werw lobby launched.
+ DRESULT (*IsLobbyLaunched)(char* sDriver);
+
+ // Gets the lobby launch info if available.
+ DRESULT (*GetLobbyLaunchInfo)(char* sDriver, void** ppLobbyLaunchData);
+
+ // Gets the tcp/ip address of the main driver if available.
+ DRESULT (*GetTcpIpAddress)(char* sAddress, DDWORD dwBufferSize);
+
+ protected:
+
+ CommonLT *m_pCommonLT;
+ CPhysicsLT *m_pPhysicsLT;
+ };
+
+
+ // For backward compatibility.. never use this.
+ #define CClientDE ClientDE
+
+
+#endif // __CLIENT_DE_H__
+
+
diff --git a/AppHeaders/clientshell_de.h b/AppHeaders/clientshell_de.h
new file mode 100644
index 0000000..c38d152
--- /dev/null
+++ b/AppHeaders/clientshell_de.h
@@ -0,0 +1,144 @@
+
+#ifndef __CLIENTSHELL_DE_H__
+#define __CLIENTSHELL_DE_H__
+
+
+ #include "basedefs_de.h"
+ #include "DStream.h"
+
+
+
+ /////////////////////////////////////////////////////////////////////
+ // ClientShell interface. This is full of callback functions that
+ // DirectEngine will call to notify you of things.
+ /////////////////////////////////////////////////////////////////////
+
+ typedef struct ClientShellDE_t* LPCLIENTSHELLDE;
+
+ typedef struct ClientShellDE_t
+ {
+
+ // This is so DirectEngine will skip over a C++ object's VTable.
+ #ifdef COMPILE_WITH_C
+ void *cpp_4BytesForVTable;
+ #endif
+
+
+ // Called after the engine has fully initialized and is ready to go!
+ // The engine doesn't initialize the renderer itself, but it passes in the
+ // default RMode it would use to initialize it (from the "RenderDLL", "ScreenWidth",
+ // and "ScreenHeight" console variables). You must call SetRenderMode to
+ // initialize the renderer in here.
+ // Initialize appGuid before returning. This controls what netgames you can query and
+ // which ones you can connect to.
+ // If this returns something other than LT_OK the engine will shutdown immediately.
+ DRESULT (*OnEngineInitialized)(LPCLIENTSHELLDE pShell, struct RMode_t *pMode, DGUID *pAppGuid);
+
+ // Called before the engine uninitializes itself.
+ void (*OnEngineTerm)(LPCLIENTSHELLDE pShell);
+
+ // Notification for when commands go on and off.
+ void (*OnCommandOn)(LPCLIENTSHELLDE pShell, int command);
+ void (*OnCommandOff)(LPCLIENTSHELLDE pShell, int command);
+
+ // Key up/down notification. Try to use command notification whenever
+ // possible because key up/down notification isn't portable.
+ void (*OnKeyDown)(LPCLIENTSHELLDE pShell, int key, int rep);
+ void (*OnKeyUp)(LPCLIENTSHELLDE pShell, int key);
+
+ // Message handler.
+ void (*OnMessage)(LPCLIENTSHELLDE pShell, DBYTE messageID, HMESSAGEREAD hMessage);
+
+ // Called when a model hits a model key.
+ void (*OnModelKey)(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, ArgList *pArgList);
+
+ // Called right before a world is loaded. After this call, it shows whatever
+ // you've drawn to the screen, then loads the world.
+ void (*PreLoadWorld)(LPCLIENTSHELLDE pShell, char *pWorldName);
+
+ // Called when you enter/exit a world. You lose ALL server objects when
+ // you exit the world, so don't reference them after exiting the world!
+ void (*OnEnterWorld)(LPCLIENTSHELLDE pShell);
+ void (*OnExitWorld)(LPCLIENTSHELLDE pShell);
+
+ // Called when the server tells the client about a special effect object.
+ void (*SpecialEffectNotify)(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, HMESSAGEREAD hMessage);
+
+ // Called when an object with client flag CF_NOTIFYONREMOVE is removed.
+ void (*OnObjectRemove)(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj);
+
+ // Called when an object is about to move.
+ DRESULT (*OnObjectMove)(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DVector *pNewPos);
+ DRESULT (*OnObjectRotate)(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DRotation *pNewRot);
+
+ void (*PreUpdate)(LPCLIENTSHELLDE pShell);
+ void (*Update)(LPCLIENTSHELLDE pShell);
+ void (*PostUpdate)(LPCLIENTSHELLDE pShell);
+
+ // The engine uses this to sync the random number generator. Just call
+ // srand() with a constant.
+ void (*SRand)(LPCLIENTSHELLDE pShell);
+
+ // Called when a demo is about to be recorded or played. Save/load the variables
+ // that will affect demo playback.
+ void (*DemoSerialize)(LPCLIENTSHELLDE pShell, DStream *pStream, DBOOL bLoad);
+
+ // Called when a particular engine event happens.
+ // Parameters:
+ // pShell - Game client shell.
+ // dwEvent - Event ID. One of the LTEVENT_ values
+ // dwParam - Event data.
+ void (*OnEvent)(LPCLIENTSHELLDE pShell, DDWORD dwEventID, DDWORD dwParam);
+
+ // Called when an object moved on the client side collides with another.
+ DRESULT (*OnTouchNotify)(LPCLIENTSHELLDE pShell, HOBJECT hMain,
+ CollisionInfo *pInfo, float forceMag);
+ } ClientShellDE;
+
+
+ #include "client_de.h"
+
+
+ class ClientDE;
+
+
+ #define CLIENTSHELL_VERSION 3
+
+ typedef ClientShellDE* (*CreateClientShellFn)(ClientDE *pClientDE);
+ typedef void (*DeleteClientShellFn)(ClientShellDE *);
+
+ // You must implement these two functions to create and delete your client shell.
+ // When you create it, you should set all of its function pointers.
+ ClientShellDE* CreateClientShell(ClientDE *pClientDE);
+ void DeleteClientShell(ClientShellDE *);
+
+ // The HINSTANCE for the DLL.
+ // You MUST set g_pClientDE to pClientDE in CreateClientShell.
+ extern void *g_hLTDLLInstance;
+ extern ClientDE *g_pClientDE;
+
+ #define SETUP_CLIENTSHELL()\
+ void *g_hLTDLLInstance=0;\
+ ClientDE *g_pClientDE=0;\
+ BEGIN_EXTERNC() \
+ __declspec(dllexport) void GetClientShellFunctions(CreateClientShellFn *pCreate, DeleteClientShellFn *pDelete);\
+ __declspec(dllexport) int GetClientShellVersion();\
+ __declspec(dllexport) void SetInstanceHandle(void *handle);\
+ END_EXTERNC()\
+ void GetClientShellFunctions(CreateClientShellFn *pCreate, DeleteClientShellFn *pDelete)\
+ {\
+ *pCreate = CreateClientShell;\
+ *pDelete = DeleteClientShell;\
+ }\
+ int GetClientShellVersion()\
+ {\
+ return CLIENTSHELL_VERSION;\
+ }\
+ void SetInstanceHandle(void *handle)\
+ {\
+ g_hLTDLLInstance = handle;\
+ }
+
+
+#endif // __CLIENTSHELL_DE_H__
+
diff --git a/AppHeaders/common_de.h b/AppHeaders/common_de.h
new file mode 100644
index 0000000..67fe617
--- /dev/null
+++ b/AppHeaders/common_de.h
@@ -0,0 +1,70 @@
+
+#ifndef __COMMON_DE_H__
+#define __COMMON_DE_H__
+
+
+ #include "basedefs_de.h"
+
+
+ class LMessage;
+
+
+ class CommonLT
+ {
+ public:
+
+ virtual ~CommonLT() {}
+
+ // Helpers.
+ public:
+
+ // Initialize the ConParse and call. Fills in m_Args and m_nArgs with each set of tokens.
+ // Returns DE_FINISHED when done. Sample loop:
+ // parse.Init(pStr);
+ // while(pEngine->Parse2(&parse) == LT_OK)
+ // {
+ // .. process args ..
+ // }
+ virtual DRESULT Parse(ConParse *pParse)=0;
+
+ // Tells you what type of object this is.
+ virtual DRESULT GetObjectType(HOBJECT hObj, DDWORD *type)=0;
+
+ // Gets a model animation's user dimensions (what they set for dimensions in ModelEdit).
+ virtual DRESULT GetModelAnimUserDims(HOBJECT hObject, DVector *pDims, HMODELANIM hAnim)=0;
+
+ // Get the vectors from a rotation.
+ virtual DRESULT GetRotationVectors(DRotation &rot, DVector &up, DVector &right, DVector &forward)=0;
+
+ // Setup the rotation based on euler angles
+ // pitch = rotation around X
+ // yaw = rotation around Y
+ // roll = rotation around Z
+ virtual DRESULT SetupEuler(DRotation &rot, float pitch, float yaw, float roll)=0;
+
+ // Start a message. Send it with a SendTo function and free it by calling LMessage::Release.
+ virtual DRESULT CreateMessage(LMessage* &pMsg)=0;
+
+
+ // Geometry stuff.
+ public:
+ // Returns DE_NOTINWORLD if no world is loaded, or DE_INSIDE if the point
+ // is in the world or DE_OUTSIDE if the point is not in the world.
+ virtual DRESULT GetPointStatus(DVector *pPoint)=0;
+
+ // Get the shade (RGB, 0-255) at the point you specify.
+ // Returns DE_NOTINWORLD if the point is outside the world.
+ virtual DRESULT GetPointShade(DVector *pPoint, DVector *pColor)=0;
+
+ // Get the texture flags from a poly. Returns DE_OK
+ // or DE_ERROR if no world is loaded or hPoly is invalid.
+ virtual DRESULT GetPolyTextureFlags(HPOLY hPoly, DDWORD *pFlags)=0;
+ };
+
+
+#endif
+
+
+
+
+
diff --git a/AppHeaders/cpp_aggregate_de.h b/AppHeaders/cpp_aggregate_de.h
new file mode 100644
index 0000000..5d83f5f
--- /dev/null
+++ b/AppHeaders/cpp_aggregate_de.h
@@ -0,0 +1,67 @@
+
+// This header file defines the base aggregate structure. Every
+// aggregate must have a link to its next one and a pointer
+// to certain functions that an aggregate must supply.
+// When implementing an aggregate, you MUST derive from this!
+// (In C, just put it as the first member in your structure..)
+
+#ifndef __CPPAGGREGATE_DE__
+#define __CPPAGGREGATE_DE__
+
+#include "serverobj_de.h"
+
+class Aggregate
+{
+ public :
+
+ // Very important that these data members are EXACTLY the same as
+ // the C version of this class (Aggregate_t)...
+ Aggregate *m_pNextAggregate;
+
+ // Hook functions for the aggregate..
+ AggregateEngineMessageFn m_EngineMessageFn;
+ AggregateObjectMessageFn m_ObjectMessageFn;
+
+
+ Aggregate()
+ {
+ m_EngineMessageFn = _EngineMessageFn;
+ m_ObjectMessageFn = _ObjectMessageFn;
+ }
+ virtual ~Aggregate() {}
+
+
+ protected :
+
+ virtual DDWORD EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, DFLOAT lData) { return 1; }
+ virtual DDWORD ObjectMessageFn(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead) { return 1; }
+
+ private :
+
+ static DDWORD _EngineMessageFn(LPBASECLASS pObject, LPAGGREGATE pAggregate, DDWORD messageID, void *pData, DFLOAT lData);
+ static DDWORD _ObjectMessageFn(LPBASECLASS pObject, LPAGGREGATE pAggregate, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+};
+
+
+// Inlines...
+inline DDWORD Aggregate::_EngineMessageFn(LPBASECLASS pObject, LPAGGREGATE pAggregate, DDWORD messageID, void *pData, DFLOAT lData)
+{
+ if (pAggregate)
+ {
+ return pAggregate->EngineMessageFn(pObject, messageID, pData, lData);
+ }
+
+ return 0;
+}
+
+inline DDWORD Aggregate::_ObjectMessageFn(LPBASECLASS pObject, LPAGGREGATE pAggregate, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
+{
+ if (pAggregate)
+ {
+ return pAggregate->ObjectMessageFn(pObject, hSender, messageID, hRead);
+ }
+
+ return 0;
+}
+
+#endif // __CPP_AGGREGATE_DE__
diff --git a/AppHeaders/cpp_client_de.h b/AppHeaders/cpp_client_de.h
new file mode 100644
index 0000000..1b64aa3
--- /dev/null
+++ b/AppHeaders/cpp_client_de.h
@@ -0,0 +1,5 @@
+
+// This is a dummy header here for backward compatibility.
+#include "client_de.h"
+
+
diff --git a/AppHeaders/cpp_clientshell_de.h b/AppHeaders/cpp_clientshell_de.h
new file mode 100644
index 0000000..53600b4
--- /dev/null
+++ b/AppHeaders/cpp_clientshell_de.h
@@ -0,0 +1,266 @@
+// ----------------------------------------------------------------------- //
+//
+// MODULE : CPP_CLIENTSHELL_DE.H
+//
+// PURPOSE : C++ DE client shell class definition
+//
+// CREATED : 9/17/97
+//
+// ----------------------------------------------------------------------- //
+
+#ifndef __CPP_CLIENTSHELL_DE_H__
+#define __CPP_CLIENTSHELL_DE_H__
+
+
+#include "clientshell_de.h"
+
+
+
+/////////////////////////////////////////////////////////////////////
+// C++ ClientShell interface. This class contains the virtual methods
+// that DirectEngine will call to notify you of things.
+/////////////////////////////////////////////////////////////////////
+
+// See ClientShellDE.h for function docs.
+class CClientShellDE
+{
+ public :
+
+ CClientShellDE();
+ virtual ~CClientShellDE() {}
+
+ CClientDE* GetClientDE() const;
+
+
+ protected :
+
+ virtual void OnCommandOn(int command) {}
+ virtual void OnCommandOff(int command) {}
+
+ virtual void OnKeyDown(int key, int rep) {}
+ virtual void OnKeyUp(int key) {}
+
+ virtual void OnMessage(DBYTE messageID, HMESSAGEREAD hMessage) {}
+
+ virtual void OnModelKey(HLOCALOBJ hObj, ArgList *pArgs) {}
+
+ virtual void PreLoadWorld(char *pWorldName) {}
+ virtual void OnEnterWorld() {}
+ virtual void OnExitWorld() {}
+
+ virtual void SpecialEffectNotify(HLOCALOBJ hObj, HMESSAGEREAD hMessage) {}
+
+ virtual void OnObjectRemove(HLOCALOBJ hObj) {}
+
+ virtual void PreUpdate() {}
+ virtual void Update() {}
+ virtual void PostUpdate() {}
+
+ virtual DRESULT OnObjectMove(HLOCALOBJ hObj, DBOOL bTeleport, DVector *pNewPos) {return LT_OK;}
+ virtual DRESULT OnObjectRotate(HLOCALOBJ hObj, DBOOL bTeleport, DRotation *pNewRot) {return LT_OK;}
+
+ virtual DRESULT OnEngineInitialized(struct RMode_t *pMode, DGUID *pAppGuid) {return LT_ERROR;}
+ virtual void OnEngineTerm() {}
+
+ virtual void OnEvent( DDWORD dwEventID, DDWORD dwParam ) {}
+
+ virtual DRESULT OnTouchNotify(HOBJECT hMain, CollisionInfo *pInfo, float forceMag) {return LT_OK;}
+
+ virtual void SRand() {srand(123);}
+ virtual void DemoSerialize(DStream *pStream, DBOOL bLoad) {}
+
+ protected : // Data members
+
+ // VERY Important that this is the first data member. Pointers to this
+ // class and pointers to ClientShellDE::m_clientShell MUST BE the same.
+ ClientShellDE m_clientShell;
+
+
+ private :
+
+ // The following static functions are called by the server, and should
+ // NOT be called directly.
+ static void _OnCommandOn(LPCLIENTSHELLDE pShell, int command);
+ static void _OnCommandOff(LPCLIENTSHELLDE pShell, int command);
+ static void _OnKeyDown(LPCLIENTSHELLDE pShell, int key, int rep);
+ static void _OnKeyUp(LPCLIENTSHELLDE pShell, int key);
+ static void _OnMessage(LPCLIENTSHELLDE pShell, DBYTE messageID, HMESSAGEREAD hMessage);
+ static void _OnModelKey(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, ArgList *pArgs);
+ static void _PreLoadWorld(LPCLIENTSHELLDE pShell, char *pWorldName);
+ static void _OnEnterWorld(LPCLIENTSHELLDE pShell);
+ static void _OnExitWorld(LPCLIENTSHELLDE pShell);
+ static void _SpecialEffectNotify(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, HMESSAGEREAD hMessage);
+ static void _OnObjectRemove(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj);
+ static void _PreUpdate(LPCLIENTSHELLDE pShell);
+ static void _Update(LPCLIENTSHELLDE pShell);
+ static void _PostUpdate(LPCLIENTSHELLDE pShell);
+ static DRESULT _OnObjectMove(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DVector *pNewPos);
+ static DRESULT _OnObjectRotate(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DRotation *pNewRot);
+ static DRESULT _OnEngineInitialized(LPCLIENTSHELLDE pShell, struct RMode_t *pMode, DGUID *pAppGuid);
+ static void _OnEngineTerm(LPCLIENTSHELLDE pShell);
+ static void _OnEvent(LPCLIENTSHELLDE pShell, DDWORD dwEventID, DDWORD dwParam);
+ static DRESULT _OnTouchNotify(LPCLIENTSHELLDE pShell, HOBJECT hMain,
+ CollisionInfo *pInfo, float forceMag);
+ static void _SRand(LPCLIENTSHELLDE pShell);
+ static void _DemoSerialize(LPCLIENTSHELLDE pShell, DStream *pStream, DBOOL bLoad);
+};
+
+// Inlines...
+
+INLINE_FN CClientShellDE::CClientShellDE()
+{
+ // Set up ClientShellDE function pointers...
+ m_clientShell.SpecialEffectNotify = _SpecialEffectNotify;
+ m_clientShell.OnObjectRemove = _OnObjectRemove;
+ m_clientShell.OnCommandOn = _OnCommandOn;
+ m_clientShell.OnCommandOff = _OnCommandOff;
+ m_clientShell.OnKeyDown = _OnKeyDown;
+ m_clientShell.OnKeyUp = _OnKeyUp;
+ m_clientShell.OnMessage = _OnMessage;
+ m_clientShell.PreLoadWorld = _PreLoadWorld;
+ m_clientShell.OnEnterWorld = _OnEnterWorld;
+ m_clientShell.OnModelKey = _OnModelKey;
+ m_clientShell.OnExitWorld = _OnExitWorld;
+ m_clientShell.PreUpdate = _PreUpdate;
+ m_clientShell.Update = _Update;
+ m_clientShell.PostUpdate = _PostUpdate;
+ m_clientShell.OnObjectMove = _OnObjectMove;
+ m_clientShell.OnObjectRotate = _OnObjectRotate;
+ m_clientShell.OnEngineInitialized = _OnEngineInitialized;
+ m_clientShell.OnEngineTerm = _OnEngineTerm;
+ m_clientShell.OnEvent = _OnEvent;
+ m_clientShell.OnTouchNotify = _OnTouchNotify;
+ m_clientShell.SRand = _SRand;
+ m_clientShell.DemoSerialize = _DemoSerialize;
+}
+
+INLINE_FN CClientDE* CClientShellDE::GetClientDE() const
+{
+ return (CClientDE*)g_pClientDE;
+}
+
+INLINE_FN void CClientShellDE::_OnCommandOn(LPCLIENTSHELLDE pShell, int command)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnCommandOn(command);
+}
+
+INLINE_FN void CClientShellDE::_OnCommandOff(LPCLIENTSHELLDE pShell, int command)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnCommandOff(command);
+}
+
+INLINE_FN void CClientShellDE::_OnKeyDown(LPCLIENTSHELLDE pShell, int key, int rep)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnKeyDown(key, rep);
+}
+
+INLINE_FN void CClientShellDE::_OnKeyUp(LPCLIENTSHELLDE pShell, int key)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnKeyUp(key);
+}
+
+INLINE_FN void CClientShellDE::_OnMessage(LPCLIENTSHELLDE pShell, DBYTE messageID, HMESSAGEREAD hMessage)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnMessage(messageID, hMessage);
+}
+
+INLINE_FN void CClientShellDE::_OnModelKey(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, ArgList *pArgList)
+{
+ ((CClientShellDE*)pShell)->OnModelKey(hObj, pArgList);
+}
+
+INLINE_FN void CClientShellDE::_PreLoadWorld(LPCLIENTSHELLDE pShell, char *pWorldName)
+{
+ ((CClientShellDE*)pShell)->PreLoadWorld(pWorldName);
+}
+
+INLINE_FN void CClientShellDE::_OnEnterWorld(LPCLIENTSHELLDE pShell)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnEnterWorld();
+}
+
+INLINE_FN void CClientShellDE::_OnExitWorld(LPCLIENTSHELLDE pShell)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->OnExitWorld();
+}
+
+INLINE_FN void CClientShellDE::_SpecialEffectNotify(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, HMESSAGEREAD hMessage)
+{
+ ((CClientShellDE*)pShell)->SpecialEffectNotify(hObj, hMessage);
+}
+
+INLINE_FN void CClientShellDE::_OnObjectRemove(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj)
+{
+ ((CClientShellDE*)pShell)->OnObjectRemove(hObj);
+}
+
+INLINE_FN void CClientShellDE::_PreUpdate(LPCLIENTSHELLDE pShell)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->PreUpdate();
+}
+
+INLINE_FN void CClientShellDE::_Update(LPCLIENTSHELLDE pShell)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->Update();
+}
+
+INLINE_FN void CClientShellDE::_PostUpdate(LPCLIENTSHELLDE pShell)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ pCShell->PostUpdate();
+}
+
+INLINE_FN DRESULT CClientShellDE::_OnObjectMove(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DVector *pNewPos)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ return pCShell->OnObjectMove(hObj, bTeleport, pNewPos);
+}
+
+INLINE_FN DRESULT CClientShellDE::_OnObjectRotate(LPCLIENTSHELLDE pShell, HLOCALOBJ hObj, DBOOL bTeleport, DRotation *pNewRot)
+{
+ CClientShellDE *pCShell = (CClientShellDE*)pShell;
+ return pCShell->OnObjectRotate(hObj, bTeleport, pNewRot);
+}
+
+INLINE_FN DRESULT CClientShellDE::_OnEngineInitialized(LPCLIENTSHELLDE pShell, struct RMode_t *pMode, DGUID *pAppGuid)
+{
+ return ((CClientShellDE*)pShell)->OnEngineInitialized(pMode, pAppGuid);
+}
+
+INLINE_FN void CClientShellDE::_OnEngineTerm(LPCLIENTSHELLDE pShell)
+{
+ ((CClientShellDE*)pShell)->OnEngineTerm();
+}
+
+INLINE_FN void CClientShellDE::_OnEvent(LPCLIENTSHELLDE pShell, DDWORD dwEventID, DDWORD dwParam)
+{
+ ((CClientShellDE*)pShell)->OnEvent( dwEventID, dwParam );
+}
+
+INLINE_FN DRESULT CClientShellDE::_OnTouchNotify(LPCLIENTSHELLDE pShell, HOBJECT hMain,
+ CollisionInfo *pInfo, float forceMag)
+{
+ return ((CClientShellDE*)pShell)->OnTouchNotify(hMain, pInfo, forceMag);
+}
+
+INLINE_FN void CClientShellDE::_SRand(LPCLIENTSHELLDE pShell)
+{
+ ((CClientShellDE*)pShell)->SRand();
+}
+
+INLINE_FN void CClientShellDE::_DemoSerialize(LPCLIENTSHELLDE pShell, DStream *pStream, DBOOL bLoad)
+{
+ ((CClientShellDE*)pShell)->DemoSerialize(pStream, bLoad);
+}
+
+#endif // __CPP_CLIENTSHELL_DE_H__
+
diff --git a/AppHeaders/cpp_engineobjects_de.cpp b/AppHeaders/cpp_engineobjects_de.cpp
new file mode 100644
index 0000000..f668c5e
--- /dev/null
+++ b/AppHeaders/cpp_engineobjects_de.cpp
@@ -0,0 +1,29 @@
+//----------------------------------------------------------
+//
+// MODULE : CPP_ENGINEOBJECTS_DE.CPP
+//
+// PURPOSE : C++ DE engine objects
+//
+// CREATED : 9/17/97
+//
+//----------------------------------------------------------
+
+#include "LMessage.h"
+#include "cpp_engineobjects_de.h"
+
+#define NO_C_BASECLASS
+#include "engineobjects.c"
+
+
+BEGIN_CLASS(BaseClass)
+ ADD_STRINGPROP(Name, "noname")
+ ADD_VECTORPROP(Pos)
+ ADD_ROTATIONPROP(Rotation)
+END_CLASS_DEFAULT_NOPARENT(BaseClass, BaseClass::_EngineMsgFn, BaseClass::_ObjectMsgFn)
+
+
+BEGIN_CLASS(StartPoint)
+END_CLASS_DEFAULT(StartPoint, BaseClass, NULL, NULL)
+
+
+
diff --git a/AppHeaders/cpp_engineobjects_de.h b/AppHeaders/cpp_engineobjects_de.h
new file mode 100644
index 0000000..f37283c
--- /dev/null
+++ b/AppHeaders/cpp_engineobjects_de.h
@@ -0,0 +1,155 @@
+// ----------------------------------------------------------------------- //
+//
+// MODULE : CPP_ENGINEOBJECTS_DE.H
+//
+// PURPOSE : C++ DE engine object class(es) definition(s)
+//
+// CREATED : 9/17/97
+//
+// ----------------------------------------------------------------------- //
+
+#ifndef __CPP_ENGINEOBJECTS_DE_H__
+#define __CPP_ENGINEOBJECTS_DE_H__
+
+#include "engineobjects_de.h"
+
+#include "serverobj_de.h"
+#include "basedefs_de.h"
+#include "cpp_aggregate_de.h"
+
+ /////////////////////////////////////////////////////////////////////
+ // C++ BaseClass interface.
+ // This is the base class of ALL objects. You MUST derive from this!
+ /////////////////////////////////////////////////////////////////////
+
+class BaseClass;
+class ServerDE;
+
+extern ServerDE *g_pServerDE;
+
+class BaseClass
+{
+ public :
+
+ BaseClass(DBYTE nType=OT_NORMAL) { m_nType = nType; }
+ virtual ~BaseClass() {}
+
+ DBYTE GetType() const { return m_nType; }
+ void SetType( DBYTE type ) { m_nType = type; }
+ static ServerDE* GetServerDE() { return (ServerDE*)g_pServerDE; }
+
+ protected :
+
+ void AddAggregate(LPAGGREGATE pAggregate);
+
+ // If you derive from BaseClass, pass your messages down to here at the
+ // end of your message loop.
+ virtual DDWORD EngineMessageFn(DDWORD messageID, void *pData, DFLOAT lData);
+
+ // Call this when you get an object message function so aggregates will get it.
+ virtual DDWORD ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+
+
+ public : // Data members
+
+ // VERY Important that these data memebers stay in this order.
+ // This version and the C version must be the same!
+
+ LPAGGREGATE m_pFirstAggregate;// The first aggregate in the linked list..
+
+ // This is always set.. you can use this to pass in an
+ // HOBJECT to the functions that require on instead of calling
+ // ObjectToHandle() every time..
+ HOBJECT m_hObject;
+
+ private :
+
+ void *m_pInternal;
+
+
+ // C++ only data...
+
+ DBYTE m_nType; // Type of object (see basedefs_de.h)
+
+
+ public: // TREAT THESE AS PRIVATE
+
+ // If you derive from BaseClass, pass your messages down to here at the
+ // end of your message loop.
+ static DDWORD _EngineMsgFn(BaseClass *pObject, DDWORD messageID, void *pData, DFLOAT lData);
+
+ // Call this when you get an object message function so aggregates will get it.
+ static DDWORD _ObjectMsgFn(BaseClass *pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+
+};
+
+// BaseClass In-line methods...
+
+inline void BaseClass::AddAggregate(LPAGGREGATE pAggregate)
+{
+ bc_AddAggregate(this, pAggregate);
+}
+
+// If you derive from BaseClass, pass your messages down to here at the
+// end of your message loop.
+
+inline DDWORD BaseClass::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT lData)
+{
+ // Set object type...
+
+ if (messageID == MID_PRECREATE && pData)
+ {
+ ObjectCreateStruct* pStruct = (ObjectCreateStruct*)pData;
+ if (pStruct && pStruct->m_ObjectType == OT_NORMAL)
+ {
+ pStruct->m_ObjectType = m_nType;
+ }
+ }
+
+ return bc_EngineMessageFn(this, messageID, pData, lData);
+}
+
+// Call this when you get an object message function so aggregates will get it.
+inline DDWORD BaseClass::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
+{
+ return bc_ObjectMessageFn(this, hSender, messageID, hRead);
+}
+
+
+// Inline statics...
+inline DDWORD BaseClass::_EngineMsgFn(LPBASECLASS pObject, DDWORD messageID, void *pData, DFLOAT lData)
+{
+ if (pObject)
+ {
+ return pObject->EngineMessageFn(messageID, pData, lData);
+ }
+
+ return 0;
+}
+
+
+inline DDWORD BaseClass::_ObjectMsgFn(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
+{
+ if (pObject)
+ {
+ return pObject->ObjectMessageFn(hSender, messageID, hRead);
+ }
+
+ return 0;
+}
+
+
+ /////////////////////////////////////////////////////////////////////
+ // C++ StartPoint class interface.
+ /////////////////////////////////////////////////////////////////////
+
+class StartPoint : public BaseClass
+{
+ public :
+
+ StartPoint() : BaseClass(OT_NORMAL) {}
+};
+
+
+#endif // __CPP_ENGINEOBJECTS_DE_H__
+
diff --git a/AppHeaders/cpp_server_de.h b/AppHeaders/cpp_server_de.h
new file mode 100644
index 0000000..b10c84f
--- /dev/null
+++ b/AppHeaders/cpp_server_de.h
@@ -0,0 +1,5 @@
+
+
+// This is a dummy header here for backward compatibility.
+#include "server_de.h"
+
diff --git a/AppHeaders/cpp_servershell_de.h b/AppHeaders/cpp_servershell_de.h
new file mode 100644
index 0000000..f5e59c4
--- /dev/null
+++ b/AppHeaders/cpp_servershell_de.h
@@ -0,0 +1,266 @@
+// ----------------------------------------------------------------------- //
+//
+// MODULE : CPP_SERVERSHELL_DE.H
+//
+// PURPOSE : C++ DE server shell class definition
+//
+// CREATED : 9/17/97
+//
+// ----------------------------------------------------------------------- //
+
+#ifndef __CPP_SERVERSHELL_DE_H__
+#define __CPP_SERVERSHELL_DE_H__
+
+#include <stdlib.h>
+#include "servershell_de.h"
+
+// Forward declarations...
+
+class BaseClass;
+class ServerDE;
+
+/////////////////////////////////////////////////////////////////////
+// C++ ServerShellDE interface. Derive your server object from this.
+/////////////////////////////////////////////////////////////////////
+
+class CServerShellDE
+{
+ public :
+
+ CServerShellDE();
+ virtual ~CServerShellDE() {}
+
+ ServerDE* GetServerDE() const;
+
+ protected : // These methods should be over-written
+
+ virtual DRESULT ServerAppMessageFn(char *pMsg) {return LT_OK;}
+
+ // Notification when new clients come in.
+ // You must create an object to represent the client.
+ // It uses the object's position to determine what the client can see.
+ virtual void OnAddClient(HCLIENT hClient) {}
+ virtual void OnRemoveClient(HCLIENT hClient) {}
+
+ virtual LPBASECLASS OnClientEnterWorld(HCLIENT hClient, void *pClientData, DDWORD clientDataLen)=0;
+ virtual void OnClientExitWorld(HCLIENT hClient) {}
+
+ // Called before and after you switch worlds.
+ virtual void PreStartWorld(DBOOL bSwitchingWorlds) {}
+ virtual void PostStartWorld() {}
+
+ // Incoming message notification.
+ virtual void OnMessage(HCLIENT hSender, DBYTE messageID, HMESSAGEREAD hMessage) {}
+ virtual void OnObjectMessage(LPBASECLASS pSender, DDWORD messageID, HMESSAGEREAD hMessage) {}
+
+ // Command notification.
+ virtual void OnCommandOn(HCLIENT hClient, int command) {}
+ virtual void OnCommandOff(HCLIENT hClient, int command) {}
+
+ // Update loop callback.. do whatever you like in here.
+ // Time since the last Update() call is passed in.
+ virtual void Update(DFLOAT timeElapsed) {}
+
+ virtual void OnPlaybackFinish() {}
+
+ virtual void CacheFiles() {}
+
+ virtual void SRand() {srand(123);}
+
+
+ private : // Data members
+
+ // VERY Important that this first data member. Pointers to this class and
+ // pointers to CServerShellDE::m_serverShell MUST BE the same.
+ ServerShellDE m_serverShell;
+
+
+ private :
+
+ // The following static functions are called by the server, and should
+ // NOT be called directly.
+ static DRESULT _ServerAppMessageFn(struct ServerShellDE_t *pShell, char *pMsg);
+
+ static void _OnAddClient(struct ServerShellDE_t *pShell, HCLIENT hClient);
+ static void _OnRemoveClient(struct ServerShellDE_t *pShell, HCLIENT hClient);
+
+ static LPBASECLASS _OnClientEnterWorld(struct ServerShellDE_t *pShell, HCLIENT hClient, void *pClientData, DDWORD clientDataLen);
+ static void _OnClientExitWorld(struct ServerShellDE_t *pShell, HCLIENT hClient);
+
+ static void _PreStartWorld(struct ServerShellDE_t *pShell, DBOOL bSwitchingWorlds);
+ static void _PostStartWorld(struct ServerShellDE_t *pShell);
+ static void _OnMessage(struct ServerShellDE_t *pShell, HCLIENT hSender, DBYTE messageID, HMESSAGEREAD hMessage);
+ static void _OnObjectMessage(struct ServerShellDE_t *pShell, LPBASECLASS pSender, DDWORD messageID, HMESSAGEREAD hMessage);
+ static void _OnCommandOn(struct ServerShellDE_t *pShell, HCLIENT hClient, int command);
+ static void _OnCommandOff(struct ServerShellDE_t *pShell, HCLIENT hClient, int command);
+ static void _Update(struct ServerShellDE_t *pShell, DFLOAT timeElapsed);
+ static void _OnPlaybackFinish(struct ServerShellDE_t *pShell);
+ static void _CacheFiles(struct ServerShellDE_t *pShell);
+ static void _SRand(struct ServerShellDE_t *pShell);
+
+};
+
+
+// Inlines...
+
+INLINE_FN CServerShellDE::CServerShellDE()
+{
+ // Set up ServerShellDE function pointers...
+ m_serverShell.ServerAppMessageFn = _ServerAppMessageFn;
+ m_serverShell.OnAddClient = _OnAddClient;
+ m_serverShell.OnRemoveClient = _OnRemoveClient;
+ m_serverShell.OnClientEnterWorld = _OnClientEnterWorld;
+ m_serverShell.OnClientExitWorld = _OnClientExitWorld;
+ m_serverShell.PreStartWorld = _PreStartWorld;
+ m_serverShell.PostStartWorld = _PostStartWorld;
+ m_serverShell.OnMessage = _OnMessage;
+ m_serverShell.OnObjectMessage = _OnObjectMessage;
+ m_serverShell.OnCommandOn = _OnCommandOn;
+ m_serverShell.OnCommandOff = _OnCommandOff;
+ m_serverShell.Update = _Update;
+ m_serverShell.OnPlaybackFinish = _OnPlaybackFinish;
+ m_serverShell.CacheFiles = _CacheFiles;
+ m_serverShell.SRand = _SRand;
+}
+
+
+INLINE_FN CServerDE* CServerShellDE::GetServerDE() const
+{
+ return (CServerDE*)g_pServerDE;
+}
+
+
+INLINE_FN DRESULT CServerShellDE::_ServerAppMessageFn(struct ServerShellDE_t *pShell, char *pMsg)
+{
+ return ((CServerShellDE*)pShell)->ServerAppMessageFn(pMsg);
+}
+
+
+INLINE_FN void CServerShellDE::_OnAddClient(struct ServerShellDE_t *pShell, HCLIENT hClient)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnAddClient(hClient);
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnRemoveClient(struct ServerShellDE_t *pShell, HCLIENT hClient)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnRemoveClient(hClient);
+ }
+}
+
+INLINE_FN LPBASECLASS CServerShellDE::_OnClientEnterWorld(struct ServerShellDE_t *pShell, HCLIENT hClient, void *pClientData, DDWORD clientDataLen)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ return (LPBASECLASS)pCSShell->OnClientEnterWorld(hClient, pClientData, clientDataLen);
+ }
+
+ return NULL;
+}
+
+INLINE_FN void CServerShellDE::_OnClientExitWorld(struct ServerShellDE_t *pShell, HCLIENT hClient)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnClientExitWorld(hClient);
+ }
+}
+
+INLINE_FN void CServerShellDE::_PreStartWorld(struct ServerShellDE_t *pShell, DBOOL bSwitchingWorlds)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->PreStartWorld(bSwitchingWorlds);
+ }
+}
+
+INLINE_FN void CServerShellDE::_PostStartWorld(struct ServerShellDE_t *pShell)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->PostStartWorld();
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnMessage(struct ServerShellDE_t *pShell, HCLIENT hSender, DBYTE messageID, HMESSAGEREAD hMessage)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnMessage(hSender, messageID, hMessage);
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnObjectMessage(struct ServerShellDE_t *pShell, LPBASECLASS pSender, DDWORD messageID, HMESSAGEREAD hMessage)
+{
+ if(pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnObjectMessage(pSender, messageID, hMessage);
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnCommandOn(struct ServerShellDE_t *pShell, HCLIENT hClient, int command)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnCommandOn(hClient, command);
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnCommandOff(struct ServerShellDE_t *pShell, HCLIENT hClient, int command)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnCommandOff(hClient, command);
+ }
+}
+
+INLINE_FN void CServerShellDE::_Update(struct ServerShellDE_t *pShell, DFLOAT timeElapsed)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->Update(timeElapsed);
+ }
+}
+
+INLINE_FN void CServerShellDE::_OnPlaybackFinish(struct ServerShellDE_t *pShell)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->OnPlaybackFinish();
+ }
+}
+
+INLINE_FN void CServerShellDE::_SRand(struct ServerShellDE_t *pShell)
+{
+ if (pShell)
+ {
+ CServerShellDE *pCSShell = (CServerShellDE*)pShell;
+ pCSShell->SRand();
+ }
+}
+
+INLINE_FN void CServerShellDE::_CacheFiles(struct ServerShellDE_t *pShell)
+{
+ ((CServerShellDE*)pShell)->CacheFiles();
+}
+
+
+#endif // __CPP_SERVERSHELL_DE_H__
+
+
diff --git a/AppHeaders/de_client.h b/AppHeaders/de_client.h
new file mode 100644
index 0000000..91d37b0
--- /dev/null
+++ b/AppHeaders/de_client.h
@@ -0,0 +1,21 @@
+
+// This file includes all the necessary client-side DirectEngine headers.
+
+#ifndef __DE_CLIENT_H__
+#define __DE_CLIENT_H__
+
+
+ #include "basedefs_de.h"
+
+ #ifdef COMPILE_WITH_C
+ #include "client_de.h"
+ #include "clientshell_de.h"
+ #else
+ #include "cpp_clientshell_de.h"
+ #endif
+
+
+#endif // __DE_CLIENT_H__
+
+
+
diff --git a/AppHeaders/de_codes.h b/AppHeaders/de_codes.h
new file mode 100644
index 0000000..d6f0385
--- /dev/null
+++ b/AppHeaders/de_codes.h
@@ -0,0 +1,251 @@
+
+// This module defines all the DirectEngine return codes.
+
+#ifndef __DE_RETURNCODES_H__
+#define __DE_RETURNCODES_H__
+
+
+ // DRESULT is used for all return values.
+ // High 8 bits: error flags
+ // Low 16 bits: error code
+ #define ERROR_FLAGS(err) ((err) & 0xFF000000)
+ #define ERROR_CODE(err) ((err) & 0xFFFF)
+
+ typedef unsigned long DRESULT;
+
+
+ #define NUM_AXIS_OFFSETS 3
+
+
+ // --------------------------------------------------------------- //
+ // Defs.
+ // --------------------------------------------------------------- //
+
+ typedef enum
+ {
+ ClientType=0,
+ ServerType
+ } ClientServerType;
+
+ // File types.
+ #define FT_MODEL 0
+ #define FT_SPRITE 1
+ #define FT_TEXTURE 2
+ #define FT_SOUND 3
+
+ // Types of global panning things.
+ #define GLOBALPAN_SKYSHADOW 0
+ #define GLOBALPAN_FOGLAYER 1
+ #define NUM_GLOBALPAN_TYPES 2
+
+
+ // NetService flags.
+ #define NETSERVICE_TCPIP (1<<0) // This is the engine's TCP/IP driver. When you call
+ // GetServiceList, you must pass in a list of IP addresses
+ // to check on, formatted like <ip:port>, separated by
+ // semicolons. The port is optional. Sample:
+ // "joe.blow.com:1322 ; 204.342.1.2:123 ; 2.3.4.5"
+
+
+ // Engine event ID's
+ #define LTEVENT_DISCONNECT 1 // Client disconnected from server. dwParam will
+ // be a error flag found in de_codes.h.
+ #define LTEVENT_SHUTDOWN 2 // Engine shutting down. dwParam will be a error
+ // flag found in de_codes.h.
+ #define LTEVENT_RENDERINIT 3 // The renderer was initialized. This is called if
+ // you call SetRenderMode or if focus was lost and
+ // regained.
+ #define LTEVENT_RENDERTERM 4 // The renderer is being shutdown. This happens when
+ // ShutdownRender is called or if the app loses focus.
+
+ #define LTEVENT_RENDERALMOSTINITTED 5 // Called when the renderer has switched into
+ // the new mode but before it reloads all the textures
+ // so you can display a loading screen.
+
+ // --------------------------------------------------------------- //
+ // Flags.
+ // --------------------------------------------------------------- //
+
+ // Flags to ClientDE::ShutdownRender.
+ #define RSHUTDOWN_MINIMIZEWINDOW 1 // Minimize the app's window.
+ #define RSHUTDOWN_HIDEWINDOW 2 // Hide the app's window.
+
+ // Flags to EndMessage2().
+ #define MESSAGE_NAGGLE (1<<0) // Setting this flag allows the engine to group the
+ // message into a larger chunk, but it might not necessarily
+ // get sent right away. This helps a lot if you're sending
+ // a bunch of small messages.
+ // NOTE: ALL naggled messages get discarded if a new world is
+ // loaded on the server to prevent old info from getting to
+ // the client, but those cases still can pop up if you send
+ // unguaranteed messages.
+ #define MESSAGE_NAGGLEFAST (1<<1) // Same as naggle but these ones are sent out 15 times per second.
+
+ // DON'T change this value.
+ #define MESSAGE_GUARANTEED (1<<7) // Send with guaranteed delivery. Try to send as many
+ // network messages as possible without guaranteed delivery.
+ // Initialization messages and stuff like that should be
+ // guaranteed but anything that can be discarded shouldn't
+ // use guaranteed delivery. Keep in mind that if you send
+ // without guaranteed delivery you can't do any kind of
+ // incremental updating, you'll have to send it periodically
+ // if you want to make sure the other side is updated on it.
+
+ #define MESSAGE_NOTHROTTLE (1<<6) // By default, the engine limits its outgoing bandwidth by
+ // dropping packets if it's sending too fast (guaranteed messages
+ // will still be guaranteed, they just take longer to get through).
+ // This forces it to send a packet regardless of how much data is
+ // being sent.
+
+
+ #define MESSAGE_NAGGLEMASK (MESSAGE_NAGGLE|MESSAGE_NAGGLEFAST)
+
+
+ // Portal flags.
+ #define PORTAL_OPEN 1
+
+ // Video playback flags.
+ #define PLAYBACK_FULLSCREEN 1
+ #define PLAYBACK_YINTERLACE 2
+
+ // Screen flip flags.
+ #define FLIPSCREEN_CANDRAWCONSOLE 1 // Setting this says it can draw the console if
+ // the console is up.
+
+ // Screen clear flags.
+ #define CLEARSCREEN_SCREEN 1 // Clear the visual screen contents.
+ #define CLEARSCREEN_RENDER 2 // You must clear with this bit any place you're about to render.
+
+ // Intersect flags.
+ #define INTERSECT_OBJECTS 1 // Try to hit objects.. small speed hit by doing so.
+ #define IGNORE_NONSOLID 2 // Ignore nonsolid objects and nonsolid surfaces. Just a helper filter.
+ #define INTERSECT_HPOLY 4 // Fill in the HPOLY for this intersection (this slows it down a little).
+
+
+ // Object net flags.
+ #define NETFLAG_ANIMUNGUARANTEED (1<<0) // Animation info sent unguaranteed.
+
+ #define NETFLAG_POSUNGUARANTEED (1<<1) // Position and rotation updates for this object
+ // are sent with unguaranteed delivery. Good for
+ // objects in netgames that move or rotate a lot.
+ // Bad for objects that stay still.
+ #define NETFLAG_ROTUNGUARANTEED (1<<2)
+
+
+ // --------------------------------------------------------------- //
+ // DE_ERROR flags.
+ // Note: on an allocation failure, the engine shuts down on the
+ // spot so there is no DE_OUTOFMEMORY error.
+ // --------------------------------------------------------------- //
+
+ #define ERROR_DISCONNECT (1<<25) // Disconnect from the server.
+ #define ERROR_SHUTDOWN (1<<26) // Shutdown everything.
+
+
+ // --------------------------------------------------------------- //
+ // Return codes.
+ // --------------------------------------------------------------- //
+
+ #define LT_OK 0 // No problem!
+ #define DE_OK 0
+
+ #define LT_ERROR 1 // Uh oh..
+ #define DE_ERROR 1
+
+ #define DE_FINISHED 2 // Done with operation.
+
+ // Video status.
+ #define VIDEO_STARTED 10
+ #define VIDEO_ERROR 11
+ #define VIDEO_PLAYING 12
+ #define VIDEO_NOTPLAYING 13
+
+ #define DE_TRIEDTOREMOVECLIENTOBJECT 20 // Tried to remove a client's object.
+ #define DE_NOTINWORLD 21 // Tried to do an operation but a world wasn't running.
+ #define DE_MISSINGFILE 22 // Missing the requested file.
+ #define DE_MISSINGWORLDMODEL 23 // Missing the requested WorldModel.
+ #define DE_INVALIDMODELFILE 24 // Invalid model file.
+ #define DE_OBJECTNOTINWORLD 25 // Tried to modify an object but it was removed from the world.
+ #define DE_CANTREMOVESERVEROBJECT 26 // Can't remove a server object from the client.
+
+ #define DE_CANTLOADGAMERESOURCES 27 // Was missing game rezfile or directory.
+ #define DE_CANTINITIALIZEINPUT 28 // Unable to initialize input.
+ #define DE_MISSINGSHELLDLL 29
+ #define DE_INVALIDSHELLDLL 30
+ #define DE_INVALIDSHELLDLLVERSION 31
+ #define DE_CANTCREATECLIENTSHELL 32
+ #define DE_UNABLETOINITSOUND 35
+ #define DE_MISSINGMUSICDLL 36
+ #define DE_INVALIDMUSICDLL 37
+ #define DE_UNABLETOINITMUSICDLL 38
+ #define DE_CANTINITDIRECTPLAY 39
+ #define DE_USERCANCELED 40 // User canceled connect dialog.
+ #define DE_MISSINGWORLDFILE 41 // Missing world file from server.
+ #define DE_INVALIDWORLDFILE 42 // Invalid world file.
+ #define DE_ERRORBINDINGWORLD 43 // Error binding world to renderer.
+ #define DE_INVALIDSERVERPACKET 44 // Got a bad packet from the server.
+ #define DE_MISSINGSPRITEFILE 45
+ #define DE_INVALIDSPRITEFILE 46
+ #define DE_MISSINGMODELFILE 47
+ #define DE_UNABLETORESTOREVIDEO 48 // Couldn't restore video mode.
+ #define DE_SERVERERROR 49 // Got an error from the server.
+ #define DE_CANTCREATESERVER 50 // Was unable to create a server.
+ #define DE_ERRORLOADINGRENDERDLL 51 // Error loading the render DLL.
+
+ #define DE_MISSINGCLASS 52 // Missing a needed class from object.dll.
+ #define DE_CANTCREATESERVERSHELL 53 // Unable to create a server shell.
+ #define DE_INVALIDOBJECTDLL 54 // Invalid (or missing) object DLL.
+ #define DE_INVALIDOBJECTDLLVERSION 55 // Invalid object DLL version.
+ #define DE_ERRORINITTINGNETDRIVER 56 // Couldn't initialize net driver.
+ #define LT_NOGAMERESOURCES 57 // No game resources specified.
+ #define DE_CANTRESTOREOBJECT 58 // Couldn't restore an object.
+
+ #define DE_NODENOTFOUND 59 // Couldn't find the specified model node.
+ #define DE_INVALIDPARAMS 60 // Invalid parameters passed to function (like NULL for an HOBJECT).
+
+ #define DE_NOTFOUND 61 // Something was not found.
+ #define DE_ALREADYEXISTS 62 // Something already exists.
+ #define DE_NOTCONNECTED 63 // Not currently on a server.
+
+ #define DE_INSIDE 64 // Inside.
+ #define DE_OUTSIDE 65 // Outside.
+
+ #define DE_INVALIDDATA 66 // Invalid data.
+ #define DE_OUTOFMEMORY 67 // Couldn't get enough memory. The engine
+ // will always shutdown before giving this
+ // error, so it's only used in tools.
+ #define DE_MISSINGPALETTE 68 // Internal.
+ #define DE_INVALIDVERSION 69 // Invalid version.
+
+ #define LT_NOCHANGE 70 // Nothing was changed.
+
+ #define LT_INPUTBUFFEROVERFLOW 71 // Input buffer overflowed.
+ #define LT_OVERFLOW 71 // Overflow (no shit).
+
+ #define LT_KEPTSAMEMODE 72 // Wasn't able to switch to new mode.
+
+ #define LT_NOTINITIALIZED 73
+ #define LT_ALREADYIN3D 74 // Already between a Start3D/End3D block.
+ #define LT_NOTIN3D 75 // Not between a Start3D/End3D block.
+
+ #define LT_ERRORCOPYINGFILE 76
+ #define LT_INVALIDFILE 77
+
+ #define LT_INVALIDNETVERSION 78 // Tried to connect to a server with a different
+ // network protocol version.
+
+ #define LT_TIMEOUT 79 // Timed out..
+
+ #define LT_CANTBINDTOPORT 80 // Couldn't bind to the requested port.
+ #define LT_REJECTED 81 // Connection rejected.
+ #define LT_NOTSAMEGUID 82 // The host you tried to connect to was running a game
+ // with a different app DGUID.
+
+ #define LT_NO3DSOUNDPROVIDER 83 // Unable to initialize the 3d sound provider
+
+
+#endif // __DE_RETURNCODES_H__
+
+
+
+
diff --git a/AppHeaders/de_server.h b/AppHeaders/de_server.h
new file mode 100644
index 0000000..1418e38
--- /dev/null
+++ b/AppHeaders/de_server.h
@@ -0,0 +1,22 @@
+
+// This header file includes all the server-side DirectEngine header files.
+#ifndef __DE_SERVER_H__
+#define __DE_SERVER_H__
+
+ #include "basedefs_de.h"
+
+ #ifdef COMPILE_WITH_C
+ #include "engineobjects_de.h"
+ #include "server_de.h"
+ #include "servershell_de.h"
+ #else
+ #include "cpp_engineobjects_de.h"
+ #include "cpp_servershell_de.h"
+ #endif
+
+ #include "serverobj_de.h"
+
+
+#endif // __DE_SERVER_H__
+
+
diff --git a/AppHeaders/dlink.h b/AppHeaders/dlink.h
new file mode 100644
index 0000000..0b8006d
--- /dev/null
+++ b/AppHeaders/dlink.h
@@ -0,0 +1,124 @@
+
+// This is for simple but very convenient doubly linked lists..
+// You need a DLink for the list head, and this just defines
+// really common routines to insert, remove, and tie off.
+
+#ifndef __DLINK_H__
+#define __DLINK_H__
+
+
+ class DLink;
+
+
+ // These are only used internally in the engine (with lots of casting)
+ // where memory is scarce for the head of a DLink list.
+ typedef struct CheapDLink_t
+ {
+ DLink *m_pPrev, *m_pNext;
+ } CheapDLink;
+
+
+
+ #include "basetypes_de.h"
+
+
+ // This goes thru and C++ deletes everything in a list.
+ // You need a DLink *pCur, *pNext;
+ #define CPP_DELETELIST(_list_pointer, type) \
+ {\
+ pCur = (_list_pointer)->m_Head.m_pNext;\
+ while(pCur != &(_list_pointer)->m_Head)\
+ {\
+ pNext = pCur->m_pNext;\
+ delete ((type*)pCur->m_pData);\
+ pCur = pNext;\
+ }\
+ dl_InitList(_list_pointer);\
+ }
+
+
+ // Use these to declare blank DLinks and DLists.
+ #define DECLARE_DLINK(name) \
+ DLink name = {&(name), &(name), 0};
+
+ #define DECLARE_DLIST(name) \
+ DList name = {0, &name.m_Head, &name.m_Head, 0};
+
+
+ class DLink
+ {
+ public:
+ // Makes it easy to traverse the list in either direction.
+ DLink* operator[](unsigned long i)
+ {
+ return ((DLink**)this)[i];
+ }
+
+ DLink *m_pPrev, *m_pNext;
+ void *m_pData;
+ };
+
+
+ INLINE_FN void dl_TieOff(DLink *pLink)
+ {
+ pLink->m_pNext = pLink->m_pPrev = pLink;
+ }
+
+ INLINE_FN void dl_Insert(DLink *pAfter, DLink *pLink)
+ {
+ pLink->m_pPrev = pAfter;
+ pLink->m_pNext = pAfter->m_pNext;
+ pLink->m_pPrev->m_pNext = pLink->m_pNext->m_pPrev = pLink;
+ }
+
+ INLINE_FN void dl_Remove(DLink *pLink)
+ {
+ pLink->m_pPrev->m_pNext = pLink->m_pNext;
+ pLink->m_pNext->m_pPrev = pLink->m_pPrev;
+ }
+
+
+ // You can use this list structure to wrap up a linked list
+ // if you want to keep a count of the elements.
+ typedef struct DList_t
+ {
+ unsigned long m_nElements;
+ DLink m_Head;
+ } DList;
+
+ INLINE_FN void dl_InitList(DList *pList)
+ {
+ dl_TieOff(&pList->m_Head);
+ pList->m_nElements = 0;
+ }
+
+ INLINE_FN void dl_AddAfter(DList *pList, DLink *pAfter, DLink *pLink, void *pObj)
+ {
+ pLink->m_pData = pObj;
+ dl_Insert(pAfter, pLink);
+ ++pList->m_nElements;
+ }
+
+ INLINE_FN void dl_AddBefore(DList *pList, DLink *pBefore, DLink *pLink, void *pObj)
+ {
+ dl_AddAfter(pList, pBefore->m_pPrev, pLink, pObj);
+ }
+
+ INLINE_FN void dl_AddHead(DList *pList, DLink *pLink, void *pObj)
+ {
+ dl_AddAfter(pList, &pList->m_Head, pLink, pObj);
+ }
+
+ INLINE_FN void dl_AddTail(DList *pList, DLink *pLink, void *pObj)
+ {
+ dl_AddAfter(pList, pList->m_Head.m_pPrev, pLink, pObj);
+ }
+
+ INLINE_FN void dl_RemoveAt(DList *pList, DLink *pLink)
+ {
+ dl_Remove(pLink);
+ --pList->m_nElements;
+ }
+
+
+#endif
diff --git a/AppHeaders/dstream.h b/AppHeaders/dstream.h
new file mode 100644
index 0000000..a114299
--- /dev/null
+++ b/AppHeaders/dstream.h
@@ -0,0 +1,67 @@
+
+#ifndef __DSTREAM_H__
+#define __DSTREAM_H__
+
+
+ // Helper macro to read/write data if your stream pointer is called pStream.
+ #define STREAM_READ(_x_) pStream->Read(&(_x_), sizeof(_x_));
+ #define STREAM_WRITE(_x_) pStream->Write(&(_x_), sizeof(_x_));
+
+
+ class DStream
+ {
+ protected:
+
+ virtual ~DStream() {}
+
+ public:
+
+ // Call this when you're done with it (same as deleting it).
+ virtual void Release()=0;
+
+ // Read in data. Returns LT_ERROR if you read past the end. ALWAYS fills in
+ // pData with 0's if it returns an error so you can safely read everything
+ // in without checking the return value every time and check ErrorStatus() at the end.
+ virtual DRESULT Read(void *pData, unsigned long size)=0;
+ virtual DRESULT ReadString(char *pStr, unsigned long maxBytes);
+
+ // LT_OK = no errors, otherwise an error occured.
+ virtual DRESULT ErrorStatus()=0;
+
+ virtual DRESULT SeekTo(unsigned long offset)=0;
+ virtual DRESULT GetPos(unsigned long *offset)=0;
+ virtual DRESULT GetLen(unsigned long *len)=0;
+
+ // Helpers to make it easy..
+ unsigned long GetPos()
+ {
+ unsigned long pos;
+ GetPos(&pos);
+ return pos;
+ }
+
+ unsigned long GetLen()
+ {
+ unsigned long len;
+ GetLen(&len);
+ return len;
+ }
+
+ template<class T>
+ DStream& operator>>(T &toRead) {Read(&toRead, sizeof(toRead)); return *this;}
+
+ // Only enabled in writeable streams.
+ public:
+
+ virtual DRESULT Write(void *pData, unsigned long size)=0;
+ virtual DRESULT WriteString(char *pStr);
+
+ template<class T>
+ DStream& operator<<(T toWrite) {Write(&toWrite, sizeof(toWrite)); return *this;}
+ };
+
+
+#endif // __DSTREAM_H__
+
+
+
diff --git a/AppHeaders/engineobjects.c b/AppHeaders/engineobjects.c
new file mode 100644
index 0000000..beb5d4d
--- /dev/null
+++ b/AppHeaders/engineobjects.c
@@ -0,0 +1,869 @@
+
+#include "serverobj_de.h"
+#include "engineobjects_de.h"
+
+
+void bc_AddAggregate(LPBASECLASS pObject, LPAGGREGATE pAggregate)
+{
+ pAggregate->m_pNextAggregate = pObject->m_pFirstAggregate;
+ pObject->m_pFirstAggregate = pAggregate;
+}
+
+
+DDWORD bc_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float fData)
+{
+ LPAGGREGATE pAggregate;
+ ObjectCreateStruct *pStruct;
+ GenericProp genProp;
+
+ // Handle ReadProp.
+ switch(messageID)
+ {
+ case MID_PRECREATE:
+ {
+ // Get the props.
+ if( fData == 1.0f || fData == 2.0f )
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+
+ if( g_pServerDE->GetPropGeneric( "Name", &genProp ) == DE_OK )
+ {
+ SAFE_STRCPY(pStruct->m_Name, genProp.m_String);
+ pStruct->m_Name[MAX_CS_FILENAME_LEN] = '\0';
+ }
+ if( g_pServerDE->GetPropGeneric( "Pos", &genProp ) == DE_OK )
+ {
+ VEC_COPY( pStruct->m_Pos, genProp.m_Vec );
+ }
+ if( g_pServerDE->GetPropGeneric( "Rotation", &genProp ) == DE_OK )
+ {
+ ROT_COPY( pStruct->m_Rotation, genProp.m_Rotation );
+ }
+ if( g_pServerDE->GetPropGeneric( "Flags", &genProp ) == DE_OK )
+ {
+ pStruct->m_Flags = genProp.m_Long;
+ }
+ if( g_pServerDE->GetPropGeneric( "Visible", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_VISIBLE;
+ else
+ pStruct->m_Flags &= ~FLAG_VISIBLE;
+ }
+ if( g_pServerDE->GetPropGeneric( "Shadow", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_SHADOW;
+ else
+ pStruct->m_Flags &= ~FLAG_SHADOW;
+ }
+ if( g_pServerDE->GetPropGeneric( "RotateableSprite", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_ROTATEABLESPRITE;
+ else
+ pStruct->m_Flags &= ~FLAG_ROTATEABLESPRITE;
+ }
+ if( g_pServerDE->GetPropGeneric( "Chromakey", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_SPRITECHROMAKEY;
+ else
+ pStruct->m_Flags &= ~FLAG_SPRITECHROMAKEY;
+ }
+ if( g_pServerDE->GetPropGeneric( "Solid", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_SOLID;
+ else
+ pStruct->m_Flags &= ~FLAG_SOLID;
+ }
+ if( g_pServerDE->GetPropGeneric( "Gravity", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_GRAVITY;
+ else
+ pStruct->m_Flags &= ~FLAG_GRAVITY;
+ }
+ if( g_pServerDE->GetPropGeneric( "TouchNotify", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_TOUCH_NOTIFY;
+ else
+ pStruct->m_Flags &= ~FLAG_TOUCH_NOTIFY;
+ }
+ if( g_pServerDE->GetPropGeneric( "Rayhit", &genProp ) == DE_OK )
+ {
+ if( genProp.m_Bool )
+ pStruct->m_Flags |= FLAG_RAYHIT;
+ else
+ pStruct->m_Flags &= ~FLAG_RAYHIT;
+ }
+ if( g_pServerDE->GetPropGeneric( "Filename", &genProp ) == DE_OK )
+ {
+ SAFE_STRCPY(pStruct->m_Filename, genProp.m_String);
+ pStruct->m_Filename[MAX_CS_FILENAME_LEN] = '\0';
+ }
+ if( g_pServerDE->GetPropGeneric( "Skin", &genProp ) == DE_OK )
+ {
+ SAFE_STRCPY(pStruct->m_SkinName, genProp.m_String);
+ pStruct->m_SkinName[MAX_CS_FILENAME_LEN] = '\0';
+ }
+ break;
+ }
+ }
+ }
+
+ // Call the aggregates.
+ pAggregate = pObject->m_pFirstAggregate;
+ while(pAggregate)
+ {
+ pAggregate->m_EngineMessageFn(pObject, pAggregate, messageID, pData, fData);
+ pAggregate = pAggregate->m_pNextAggregate;
+ }
+
+ // Default return is 1.
+ return 1;
+}
+
+DDWORD bc_ObjectMessageFn(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
+{
+ LPAGGREGATE pAggregate;
+
+ // Call the aggregates.
+ pAggregate = pObject->m_pFirstAggregate;
+ while(pAggregate)
+ {
+ pAggregate->m_ObjectMessageFn(pObject, pAggregate, hSender, messageID, hRead);
+ pAggregate = pAggregate->m_pNextAggregate;
+ }
+
+ return 1;
+}
+
+
+#ifdef COMPILE_WITH_C
+ BEGIN_CLASS(BaseClass)
+ ADD_STRINGPROP(Name, "noname")
+ ADD_VECTORPROP(Pos)
+ ADD_ROTATIONPROP(Rotation)
+ END_CLASS_DEFAULT_NOPARENT(BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn)
+#endif
+
+
+
+// The model class..
+typedef struct
+{
+ BaseClass m_BaseClass;
+} Model;
+
+static DDWORD mdl_MessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ if(messageID == MID_PRECREATE)
+ {
+ ((ObjectCreateStruct*)pData)->m_ObjectType = OT_MODEL;
+ }
+
+ // Pass the message down to the base class.
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(Model)
+ ADD_STRINGPROP(Filename, "")
+ ADD_STRINGPROP(Skin, "")
+ ADD_LONGINTPROP(Flags, FLAG_VISIBLE)
+END_CLASS_DEFAULT_FLAGS(Model, BaseClass, mdl_MessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+// The WorldModel class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+} WorldModel;
+
+static DDWORD wmdl_MessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ ObjectCreateStruct *pStruct;
+
+ if(messageID == MID_PRECREATE)
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+
+ pStruct->m_ObjectType = OT_WORLDMODEL;
+
+ if( lData == 1.0f )
+ {
+ g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN);
+ }
+ }
+
+ // Pass the message down to the base class.
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(WorldModel)
+ ADD_LONGINTPROP(Flags, FLAG_VISIBLE)
+END_CLASS_DEFAULT_FLAGS(WorldModel, BaseClass, wmdl_MessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+// The Container class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+ DDWORD m_ContainerCode;
+} Container;
+
+
+static DDWORD cntr_MessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ ObjectCreateStruct *pStruct;
+ long code;
+
+ if(messageID == MID_PRECREATE)
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+ pStruct->m_ObjectType = OT_CONTAINER;
+
+ if( lData == 1.0f )
+ {
+ code = 0;
+ g_pServerDE->GetPropLongInt("ContainerCode", &code);
+ pStruct->m_ContainerCode = (D_WORD)code;
+ g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN);
+ }
+ }
+
+ // Pass the message down to the base class.
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(Container)
+ ADD_LONGINTPROP(Flags, FLAG_VISIBLE)
+ ADD_LONGINTPROP(ContainerCode, 0)
+END_CLASS_DEFAULT_FLAGS(Container, BaseClass, cntr_MessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+// The sprite class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+ DBYTE m_Color[4]; // RGBA
+} Sprite;
+
+static DDWORD spr_MessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ ObjectCreateStruct *pStruct;
+ Sprite *pSprite;
+ GenericProp prop;
+
+ pSprite = (Sprite*)pObject;
+ switch(messageID)
+ {
+ case MID_PRECREATE:
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+ pStruct->m_ObjectType = OT_SPRITE;
+
+ g_pServerDE->GetPropGeneric("Color", &prop);
+ pSprite->m_Color[0] = (DBYTE)prop.m_Color.x;
+ pSprite->m_Color[1] = (DBYTE)prop.m_Color.y;
+ pSprite->m_Color[2] = (DBYTE)prop.m_Color.z;
+
+ g_pServerDE->GetPropGeneric("Scale", &prop);
+ VEC_COPY(pStruct->m_Scale, prop.m_Vec);
+
+ g_pServerDE->GetPropGeneric("Alpha", &prop);
+ pSprite->m_Color[3] = (DBYTE)(prop.m_Float * 255.0f);
+ }
+ break;
+
+ case MID_INITIALUPDATE:
+ {
+ g_pServerDE->SetObjectColor(pObject->m_hObject,
+ pSprite->m_Color[0]/255.0f, pSprite->m_Color[1]/255.0f,
+ pSprite->m_Color[1]/255.0f, pSprite->m_Color[3]/255.0f);
+ }
+ break;
+ }
+
+ // Pass the message down to the base class.
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(Sprite)
+ ADD_STRINGPROP(Filename, "")
+ ADD_LONGINTPROP(Flags, FLAG_VISIBLE)
+ ADD_VECTORPROP_VAL(Scale, 1, 1, 1)
+ ADD_COLORPROP(Color, 255, 255, 255)
+ ADD_REALPROP(Alpha, 1)
+END_CLASS_DEFAULT_FLAGS(Sprite, BaseClass, spr_MessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+// sound class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+ char m_Filename[101];
+ float m_fOuterRadius;
+ float m_fInnerRadius;
+ DBYTE m_nVolume;
+ DBOOL m_bAmbient;
+ DBOOL m_bFileStream;
+ unsigned char m_nPriority;
+} Sound;
+
+static DDWORD as_MessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ ObjectCreateStruct *pStruct;
+ Sound *pSound;
+ GenericProp genProp;
+
+ if(messageID == MID_PRECREATE)
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+ pSound = (Sound*)pObject;
+
+ pStruct->m_ObjectType = OT_NORMAL;
+
+ if( lData == 0.0f )
+ {
+ pSound->m_fOuterRadius = 100.0f;
+ pSound->m_fInnerRadius = 10.0f;
+
+ pSound->m_nVolume = 100;
+
+ pSound->m_nPriority = 0;
+ pSound->m_bAmbient = DTRUE;
+ pSound->m_bFileStream = DFALSE;
+ }
+ else
+ {
+ if( g_pServerDE->GetPropGeneric( "Filename", &genProp ) == DE_OK )
+ {
+ SAFE_STRCPY(pSound->m_Filename, genProp.m_String);
+ }
+ else
+ pSound->m_Filename[0] = '\0';
+
+ if( g_pServerDE->GetPropGeneric("OuterRadius", &genProp ) == DE_OK )
+ pSound->m_fOuterRadius = genProp.m_Float;
+ else
+ pSound->m_fOuterRadius = 100.0f;
+
+ if( g_pServerDE->GetPropGeneric("InnerRadius", &genProp ) == DE_OK )
+ pSound->m_fInnerRadius = genProp.m_Float;
+ else
+ pSound->m_fInnerRadius = 10.0f;
+
+ if( g_pServerDE->GetPropGeneric("Volume", &genProp) == DE_OK )
+ pSound->m_nVolume = (DBYTE)genProp.m_Long;
+ else
+ pSound->m_nVolume = 100;
+
+ if( g_pServerDE->GetPropGeneric("Priority", &genProp) == DE_OK )
+ pSound->m_nPriority = (unsigned char)genProp.m_Long;
+ else
+ pSound->m_nPriority = 0;
+
+ if( g_pServerDE->GetPropGeneric("Ambient", &genProp) == DE_OK )
+ pSound->m_bAmbient = genProp.m_Bool;
+ else
+ pSound->m_bAmbient = DTRUE;
+
+ if( g_pServerDE->GetPropGeneric("FileStream", &genProp) == DE_OK )
+ pSound->m_bFileStream = genProp.m_Bool;
+ else
+ pSound->m_bFileStream = DTRUE;
+ }
+ }
+ else if(messageID == MID_INITIALUPDATE)
+ {
+ PlaySoundInfo playSoundInfo;
+
+ PLAYSOUNDINFO_INIT( playSoundInfo );
+ playSoundInfo.m_dwFlags = PLAYSOUND_LOOP;
+ SAFE_STRCPY(playSoundInfo.m_szSoundName, (( Sound * )pObject )->m_Filename);
+ playSoundInfo.m_nPriority = (( Sound * )pObject )->m_nPriority;
+ playSoundInfo.m_fOuterRadius = (( Sound * )pObject )->m_fOuterRadius;
+ playSoundInfo.m_fInnerRadius = (( Sound * )pObject )->m_fInnerRadius;
+ if( (( Sound * )pObject )->m_nVolume < 100 )
+ {
+ playSoundInfo.m_nVolume = (( Sound * )pObject )->m_nVolume;
+ playSoundInfo.m_dwFlags |= PLAYSOUND_CTRL_VOL;
+ }
+ g_pServerDE->GetObjectPos( pObject->m_hObject, &playSoundInfo.m_vPosition );
+ if( (( Sound * )pObject )->m_bAmbient )
+ {
+ playSoundInfo.m_dwFlags |= PLAYSOUND_AMBIENT;
+ }
+ else
+ {
+ playSoundInfo.m_dwFlags |= PLAYSOUND_3D;
+ }
+
+ if((( Sound * )pObject )->m_bFileStream )
+ {
+ playSoundInfo.m_dwFlags |= PLAYSOUND_FILESTREAM | PLAYSOUND_TIMESYNC;
+ }
+
+ g_pServerDE->PlaySound( &playSoundInfo );
+
+ // sounds just remove themselves right away. Since they don't do
+ // anything right now, they just take up memory.
+ g_pServerDE->RemoveObject(pObject->m_hObject);
+ }
+
+ // Pass the message down to the base class.
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(Sound)
+ ADD_STRINGPROP(Filename, "")
+ ADD_LONGINTPROP(Priority, 0.0f)
+ ADD_REALPROP_FLAG(OuterRadius, 100.0f, PF_RADIUS)
+ ADD_REALPROP_FLAG(InnerRadius, 10.0f, PF_RADIUS)
+ ADD_LONGINTPROP(Volume, 100.0f)
+ ADD_BOOLPROP(Ambient, 1)
+ ADD_BOOLPROP(FileStream, 0)
+END_CLASS_DEFAULT_FLAGS(Sound, BaseClass, as_MessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+// Start point class.
+
+#ifdef COMPILE_WITH_C
+
+typedef struct
+{
+ BaseClass m_BaseClass;
+} StartPoint;
+
+BEGIN_CLASS(StartPoint)
+END_CLASS_DEFAULT_FLAGS(StartPoint, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+#endif // COMPILE_WITH_C
+
+
+
+// OutsideDef class.
+// These are used if you want the preprocessor to make a leak file for a level.
+typedef struct
+{
+ BaseClass m_BaseClass;
+} OutsideDef;
+
+BEGIN_CLASS(OutsideDef)
+END_CLASS_DEFAULT_FLAGS(OutsideDef, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME )
+
+
+
+// FastApproxArea class.
+// This defines an area where only fast approximation vising will occur. The
+// area is bounded by hullmakers and portals.
+typedef struct
+{
+ BaseClass m_BaseClass;
+} FastApproxArea;
+
+BEGIN_CLASS(FastApproxArea)
+END_CLASS_DEFAULT_FLAGS(FastApproxArea, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME )
+
+
+
+// Light class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+} Light;
+
+BEGIN_CLASS(Light)
+ ADD_BOOLPROP(ClipLight, 1)
+ ADD_BOOLPROP(LightObjects, 1)
+ ADD_REALPROP_FLAG(LightRadius, 300.0f, PF_RADIUS)
+ ADD_COLORPROP(LightColor, 255.0f, 255.0f, 255.0f)
+ ADD_COLORPROP(OuterColor, 0.0f, 0.0f, 0.0f)
+ ADD_REALPROP(BrightScale, 1.0f)
+ ADD_REALPROP(Time, 0.0f)
+END_CLASS_DEFAULT_FLAGS(Light, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME )
+
+
+// ObjectLight class (these lights only light objects.. they don't light the world). These
+// are used for landscape areas lit by GlobalDirLights (which don't light objects).
+typedef struct
+{
+ BaseClass m_BaseClass;
+} ObjectLight;
+
+BEGIN_CLASS(ObjectLight)
+ ADD_REALPROP_FLAG(LightRadius, 300.0f, PF_RADIUS)
+ ADD_COLORPROP(LightColor, 255.0f, 255.0f, 255.0f)
+ ADD_COLORPROP(OuterColor, 0.0f, 0.0f, 0.0f)
+ ADD_REALPROP(BrightScale, 1.0f)
+END_CLASS_DEFAULT_FLAGS(ObjectLight, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
+
+// DirLight class (just uses the Light code).
+typedef struct DirLight_t
+{
+ BaseClass m_BaseClass;
+} DirLight;
+
+BEGIN_CLASS(DirLight)
+ ADD_BOOLPROP(LightObjects, 1)
+ ADD_BOOLPROP(ClipLight, 1)
+ ADD_REALPROP_FLAG(LightRadius, 300.0f, PF_RADIUS)
+ ADD_COLORPROP(InnerColor, 255.0f, 255.0f, 255.0f)
+ ADD_COLORPROP(OuterColor, 0.0f, 0.0f, 0.0f)
+ ADD_REALPROP_FLAG(FOV, 90.0f, PF_FIELDOFVIEW)
+ ADD_REALPROP(BrightScale, 1.0f)
+ ADD_REALPROP(Time, 0.0f)
+END_CLASS_DEFAULT_FLAGS(DirLight, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
+
+// LightAnimator class.
+typedef struct LightAnimator_t
+{
+ BaseClass m_BaseClass;
+} LightAnimator;
+
+BEGIN_CLASS(LightAnimator)
+ ADD_STRINGPROP(BaseLightName, "light")
+END_CLASS_DEFAULT_FLAGS(LightAnimator, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
+// ProjectorSprite.
+typedef struct ProjectorSprite_t
+{
+ BaseClass m_BaseClass;
+} ProjectorSprite;
+
+BEGIN_CLASS(ProjectorSprite)
+ ADD_STRINGPROP(Filename, "sprite.spr")
+END_CLASS_DEFAULT_FLAGS(ProjectorSprite, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
+
+// GlobalDirLight class (just uses the Light code).
+typedef struct GlobalDirLight_t
+{
+ BaseClass m_BaseClass;
+} GlobalDirLight;
+
+BEGIN_CLASS(GlobalDirLight)
+ ADD_VECTORPROP_VAL_FLAG(BigDims, 90.0f, 90.0f, 90.0f, PF_DIMS|PF_HIDDEN)
+ ADD_COLORPROP(InnerColor, 255.0f, 255.0f, 255.0f)
+ ADD_COLORPROP(OuterColor, 0.0f, 0.0f, 0.0f)
+ ADD_REALPROP(BrightScale, 1.0f)
+END_CLASS_DEFAULT_FLAGS(GlobalDirLight, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
+
+// World class..
+typedef struct
+{
+ BaseClass m_BaseClass;
+} World;
+
+BEGIN_CLASS(World)
+END_CLASS_DEFAULT_FLAGS(World, BaseClass, DNULL, DNULL, CF_ALWAYSLOAD)
+
+
+
+
+// Brush class.
+typedef struct
+{
+ BaseClass m_BaseClass;
+} Brush;
+
+
+BEGIN_CLASS(Brush)
+ ADD_BOOLPROP(Solid, 1)
+ ADD_BOOLPROP(Nonexistant, 0)
+ ADD_BOOLPROP(Invisible, 0)
+ ADD_BOOLPROP(Translucent, 0)
+ ADD_BOOLPROP(SkyPortal, 0)
+ ADD_BOOLPROP(FullyBright, 0)
+ ADD_BOOLPROP(FlatShade, 0)
+ ADD_BOOLPROP(GouraudShade, 1)
+ ADD_BOOLPROP(LightMap, 1)
+ ADD_BOOLPROP(Subdivide, 1)
+ ADD_BOOLPROP(HullMaker, 0)
+ ADD_BOOLPROP(AlwaysLightMap, 0)
+ ADD_BOOLPROP(DirectionalLight, 0)
+ ADD_BOOLPROP(Portal, 0)
+ ADD_BOOLPROP(NoSnap, 0)
+ ADD_BOOLPROP(SkyPan, 0)
+
+ ADD_LONGINTPROP(DetailLevel, 0)
+ ADD_STRINGPROP(Effect, "")
+ ADD_STRINGPROP(EffectParam, "")
+ ADD_REALPROP(FrictionCoefficient, 1)
+END_CLASS_DEFAULT_FLAGS(Brush, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+// DemoSkyWorldModel class. This is a WorldModel that adds itself to the sky object
+// list and has properties that level designers can edit to set the sky dimensions.
+// If the sky box is set to zero, then it won't set it. (This is so you can have
+// multiple DemoSkyWorldModels in the world, and only one sets the sky box).
+// The DemoSkyWorldModel uses InnerPercentX, Y, and Z as a percentage of the
+// SkyDims box for the inner box.
+// Each sky world model must have a (unique) index from 0-30. Ones with
+// lower indices get drawn first.
+typedef struct
+{
+ BaseClass BaseClass;
+ DVector SkyDims;
+ float InnerPercentX, InnerPercentY, InnerPercentZ;
+ long Index;
+} DemoSkyWorldModel;
+
+
+static DDWORD DemoSky_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ DemoSkyWorldModel *pModel;
+ SkyDef def;
+ DVector pos, temp;
+ ObjectCreateStruct *pStruct;
+ HOBJECT hObject;
+
+ pModel = (DemoSkyWorldModel*)pObject;
+ switch(messageID)
+ {
+ case MID_PRECREATE:
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+
+ pStruct->m_ObjectType = OT_WORLDMODEL;
+
+ if( lData == 1.0f )
+ {
+ g_pServerDE->GetPropVector("SkyDims", &pModel->SkyDims);
+ g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN);
+ g_pServerDE->GetPropReal("InnerPercentX", &pModel->InnerPercentX);
+ g_pServerDE->GetPropReal("InnerPercentY", &pModel->InnerPercentY);
+ g_pServerDE->GetPropReal("InnerPercentZ", &pModel->InnerPercentZ);
+ g_pServerDE->GetPropLongInt("Index", &pModel->Index);
+ }
+ else
+ {
+ VEC_INIT( pModel->SkyDims );
+ pModel->InnerPercentX = 0.1f;
+ pModel->InnerPercentY = 0.1f;
+ pModel->InnerPercentZ = 0.1f;
+ pModel->Index = 0;
+ }
+ break;
+ }
+
+ case MID_INITIALUPDATE:
+ {
+ // Set the sky box?
+ if(pModel->SkyDims.x != 0.0f && pModel->SkyDims.y != 0.0f && pModel->SkyDims.z != 0.0f)
+ {
+ g_pServerDE->GetObjectPos(pModel->BaseClass.m_hObject, &pos);
+ VEC_SUB(def.m_Min, pos, pModel->SkyDims);
+ VEC_ADD(def.m_Max, pos, pModel->SkyDims);
+
+ temp.x = pModel->SkyDims.x * pModel->InnerPercentX;
+ temp.y = pModel->SkyDims.y * pModel->InnerPercentY;
+ temp.z = pModel->SkyDims.z * pModel->InnerPercentZ;
+
+ VEC_SUB(def.m_ViewMin, pos, temp);
+ VEC_ADD(def.m_ViewMax, pos, temp);
+
+ g_pServerDE->SetSkyDef(&def);
+ }
+
+ hObject = pModel->BaseClass.m_hObject;
+ g_pServerDE->SetObjectFlags(hObject, g_pServerDE->GetObjectFlags(hObject) | (FLAG_SKYOBJECT|FLAG_FORCEOPTIMIZEOBJECT));
+ g_pServerDE->AddObjectToSky(pModel->BaseClass.m_hObject, pModel->Index);
+ break;
+ }
+ }
+
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+
+BEGIN_CLASS(DemoSkyWorldModel)
+ ADD_VECTORPROP_VAL_FLAG(SkyDims, 0.0f, 0.0f, 0.0f, PF_DIMS)
+ ADD_LONGINTPROP(Flags, 1)
+ ADD_LONGINTPROP(Index, 0)
+ ADD_REALPROP(InnerPercentX, 0.1f)
+ ADD_REALPROP(InnerPercentY, 0.1f)
+ ADD_REALPROP(InnerPercentZ, 0.1f)
+END_CLASS_DEFAULT_FLAGS(DemoSkyWorldModel, BaseClass, DemoSky_EngineMessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+
+// This works exactly the same as a DemoSkyWorldModel, except you identify the object by name.
+typedef struct
+{
+ BaseClass BaseClass;
+ DVector SkyDims;
+ float InnerPercentX, InnerPercentY, InnerPercentZ;
+ long Index;
+ char m_ObjectName[100];
+ HOBJECT m_hObject;
+} SkyPointer;
+
+
+static DDWORD SkyPointer_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ SkyPointer *pModel;
+ SkyDef def;
+ DVector pos, temp;
+ ObjectCreateStruct *pStruct;
+ ObjectList *pList;
+ HOBJECT hObject;
+
+ pModel = (SkyPointer*)pObject;
+ switch(messageID)
+ {
+ case MID_PRECREATE:
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+
+ pStruct->m_ObjectType = OT_NORMAL;
+ pModel->m_hObject = 0;
+
+ if( lData == 1.0f )
+ {
+ g_pServerDE->GetPropVector("SkyDims", &pModel->SkyDims);
+ g_pServerDE->GetPropString("Name", pStruct->m_Filename, MAX_CS_FILENAME_LEN);
+ g_pServerDE->GetPropString("SkyObjectName", pModel->m_ObjectName, sizeof(pModel->m_ObjectName)-1);
+ g_pServerDE->GetPropReal("InnerPercentX", &pModel->InnerPercentX);
+ g_pServerDE->GetPropReal("InnerPercentY", &pModel->InnerPercentY);
+ g_pServerDE->GetPropReal("InnerPercentZ", &pModel->InnerPercentZ);
+ g_pServerDE->GetPropLongInt("Index", &pModel->Index);
+ }
+ else
+ {
+ pModel->m_ObjectName[0] = 0;
+ VEC_INIT( pModel->SkyDims );
+ pModel->InnerPercentX = 0.1f;
+ pModel->InnerPercentY = 0.1f;
+ pModel->InnerPercentZ = 0.1f;
+ pModel->Index = 0;
+ }
+ break;
+ }
+
+ case MID_INITIALUPDATE:
+ {
+ // Set the sky box?
+ if(pModel->SkyDims.x != 0.0f && pModel->SkyDims.y != 0.0f && pModel->SkyDims.z != 0.0f)
+ {
+ g_pServerDE->GetObjectPos(pModel->BaseClass.m_hObject, &pos);
+ VEC_SUB(def.m_Min, pos, pModel->SkyDims);
+ VEC_ADD(def.m_Max, pos, pModel->SkyDims);
+
+ temp.x = pModel->SkyDims.x * pModel->InnerPercentX;
+ temp.y = pModel->SkyDims.y * pModel->InnerPercentY;
+ temp.z = pModel->SkyDims.z * pModel->InnerPercentZ;
+
+ VEC_SUB(def.m_ViewMin, pos, temp);
+ VEC_ADD(def.m_ViewMax, pos, temp);
+
+ g_pServerDE->SetSkyDef(&def);
+ }
+
+ g_pServerDE->SetNextUpdate(pModel->BaseClass.m_hObject, 0.001f);
+ break;
+ }
+
+ case MID_UPDATE:
+ {
+ // Add the first object to the sky.
+ pList = g_pServerDE->FindNamedObjects(pModel->m_ObjectName);
+ if(pList && pList->m_pFirstLink)
+ {
+ hObject = pList->m_pFirstLink->m_hObject;
+ g_pServerDE->AddObjectToSky(hObject, pModel->Index);
+ g_pServerDE->SetObjectFlags(hObject, g_pServerDE->GetObjectFlags(hObject) | (FLAG_SKYOBJECT|FLAG_FORCEOPTIMIZEOBJECT));
+ g_pServerDE->RelinquishList(pList);
+ }
+
+ g_pServerDE->RemoveObject(pModel->BaseClass.m_hObject);
+ break;
+ }
+ }
+
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+
+BEGIN_CLASS(SkyPointer)
+ ADD_STRINGPROP(SkyObjectName, "")
+ ADD_VECTORPROP_VAL_FLAG(SkyDims, 0.0f, 0.0f, 0.0f, PF_DIMS)
+ ADD_LONGINTPROP(Flags, 1)
+ ADD_LONGINTPROP(Index, 0)
+ ADD_REALPROP(InnerPercentX, 0.1f)
+ ADD_REALPROP(InnerPercentY, 0.1f)
+ ADD_REALPROP(InnerPercentZ, 0.1f)
+END_CLASS_DEFAULT_FLAGS(SkyPointer, BaseClass, SkyPointer_EngineMessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+// These generate areas of fog.
+typedef struct FogSphere_t
+{
+ BaseClass m_BaseClass;
+ float m_Radius;
+} FogSphere;
+
+static DDWORD FogSphere_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float lData)
+{
+ ObjectCreateStruct *pStruct;
+ GenericProp prop;
+ FogSphere *pSphere;
+
+
+ pSphere = (FogSphere*)pObject;
+ switch(messageID)
+ {
+ case MID_PRECREATE:
+ {
+ pStruct = (ObjectCreateStruct*)pData;
+ pStruct->m_ObjectType = OT_LIGHT;
+ pStruct->m_Flags = FLAG_VISIBLE | FLAG_FOGLIGHT;
+
+ g_pServerDE->GetPropGeneric("LightRadius", &prop);
+ pSphere->m_Radius = prop.m_Float;
+ }
+ break;
+
+ case MID_INITIALUPDATE:
+ {
+ g_pServerDE->SetLightRadius(pObject->m_hObject, pSphere->m_Radius);
+ }
+ break;
+ }
+
+ return bc_EngineMessageFn(pObject, messageID, pData, lData);
+}
+
+BEGIN_CLASS(FogSphere)
+ ADD_REALPROP_FLAG(LightRadius, 300.0f, PF_RADIUS)
+END_CLASS_DEFAULT_FLAGS(FogSphere, BaseClass, FogSphere_EngineMessageFn, bc_ObjectMessageFn, CF_ALWAYSLOAD)
+
+
+
+// These objects, when used with the preprocessor's -RaySelect flag, will cause the
+// first brush this object's forward vector hits to be selected in the ED file.
+typedef struct RaySelecter_t
+{
+ BaseClass m_BaseClass;
+} RaySelecter;
+
+BEGIN_CLASS(RaySelecter)
+END_CLASS_DEFAULT_FLAGS(RaySelecter, BaseClass, bc_EngineMessageFn, bc_ObjectMessageFn, CF_NORUNTIME)
+
+
diff --git a/AppHeaders/engineobjects_de.h b/AppHeaders/engineobjects_de.h
new file mode 100644
index 0000000..d040ebd
--- /dev/null
+++ b/AppHeaders/engineobjects_de.h
@@ -0,0 +1,62 @@
+
+#ifndef __ENGINEOBJECTS_DE_H__
+#define __ENGINEOBJECTS_DE_H__
+
+#include "basedefs_de.h"
+
+ /*
+ This is the very base class. You MUST derive from this!
+ For C inheritance, you should put the structure you're inheriting
+ from at the front of the derived structure like this:
+
+ typedef struct
+ {
+
+ // m_BaseObject goes first!
+ BaseClass m_BaseObject;
+
+ int blah, blah2, blah3;
+ int someVariable;
+
+ } DerivedClass;
+ */
+
+
+ // You must derive from BaseClass. BaseClass defines the Position and Rotation
+ // properties (all objects must have these). It also responds to:
+ // Flags - PT_LONGINT
+ // Filename - PT_STRING
+ // Skin - PT_STRING
+ // SoundRadius - PT_REAL
+ // You can define properties in your objects with those names and BaseClass
+ // will use them.
+ #ifdef COMPILE_WITH_C
+ typedef struct BaseClass_t
+ {
+ // This is so DirectEngine will skip over a C++ object's VTable.
+ void *cpp_4BytesForVTable;
+
+ // The first aggregate in the linked list..
+ struct Aggregate_t *m_pFirstAggregate;
+
+ // This is always set.. you can use this to pass in an
+ // HOBJECT to the functions that require on instead of calling
+ // ObjectToHandle() every time..
+ HOBJECT m_hObject;
+ } BaseClass;
+ #endif
+
+ // If you derive from BaseClass, pass your messages down to here at the
+ // end of your message loop.
+ DDWORD bc_EngineMessageFn(LPBASECLASS pObject, DDWORD messageID, void *pData, float fData);
+
+ // Call this when you get an object message function so aggregates will get it.
+ DDWORD bc_ObjectMessageFn(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+
+ // When your object initializes, pass in your aggregate here..
+ void bc_AddAggregate(LPBASECLASS pObject, LPAGGREGATE pAggregate);
+
+
+
+#endif // __ENGINEOBJECTS_DE_H__
+
diff --git a/AppHeaders/generic_msg_de.h b/AppHeaders/generic_msg_de.h
new file mode 100644
index 0000000..8b1a17d
--- /dev/null
+++ b/AppHeaders/generic_msg_de.h
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------- //
+//
+// MODULE : Generic_msg_de.h
+//
+// PURPOSE : Generic game message ids
+//
+// CREATED : 10/8/97
+//
+// ----------------------------------------------------------------------- //
+
+#ifndef __GENERIC_MSG_DE_H__
+#define __GENERIC_MSG_DE_H__
+
+// Defines...
+
+// All of the following messages are sent between objects:
+// (i.e., Object <-> Object)
+
+// For MID_TRIGGER, the message should contain 1 HSTRING that represents
+// the trigger functionality (e.g. "CLOSE")
+//
+#define MID_TRIGGER 1000
+
+// For MID_DAMAGE, the message should contain (in order) 1 DVector that
+// represents the direction the damage came from, and 1 DFLOAT that represents
+// the damage amount
+//
+#define MID_DAMAGE 1001
+
+// For MID_REPAIR, the message should contain 1 DFLOAT that represents the
+// repair amount
+//
+#define MID_REPAIR 1002
+
+// For MID_HEAL, the message should contain 1 DFLOAT that represents the
+// heal amount
+//
+#define MID_HEAL 1003
+
+// For MID_ADDWEAPON, the message should contain (in order), 1 DBYTE that
+// represents the weapon id (this id may be game specific), and 1 DFLOAT
+// that represents the amount of ammo the weapon contains
+//
+#define MID_ADDWEAPON 1004
+
+// For MID_PICKEDUP, the message should contain 1 float that represents
+// the time to remain invisible. Specify -1.0 to use the object's default
+// respawn time.
+#define MID_PICKEDUP 1005
+
+// For MID_INVENTORYITEMTOUCH, the message should contain (in order),
+// 1 DBYTE that specifies the type of item, and 1 HSTRING that specifies
+// the name of the item
+#define MID_INVENTORYITEMTOUCH 1006
+
+// For MID_INVENTORYITEMNEEDED, the message should contain (in order),
+// 1 DBYTE that specifies the type of item needed, and 1 HSTRING that
+// identifies the name of the item needed
+#define MID_INVENTORYITEMQUERY 1007
+
+// For MID_INVENTORYITEMHAVE, the message should contain (in order),
+// 1 DBYTE that specifies the type of item, and 1 HSTRING that identifies
+// the name of the item (should both be the same as in the query).
+#define MID_INVENTORYQUERYRESPONSE 1008
+
+// For MID_AMMO, the message should contain (in order), 1 DBYTE that
+// represents the ammo type (this id may be game specific), and 1 DFLOAT
+// that represents the amount of ammo.
+//
+#define MID_ADDAMMO 1009
+
+#endif // __GENERIC_MSG_DE_H__ \ No newline at end of file
diff --git a/AppHeaders/lmessage.h b/AppHeaders/lmessage.h
new file mode 100644
index 0000000..51f12ca
--- /dev/null
+++ b/AppHeaders/lmessage.h
@@ -0,0 +1,123 @@
+
+// This file defines the LMessage class, which handles reading/writing of messages.
+
+#ifndef __LMESSAGE_H__
+#define __LMESSAGE_H__
+
+
+ #include <stdio.h>
+ #include "basedefs_de.h"
+
+
+ #define OPERATOR_READ(type, fn) \
+ LMessage& operator>>(type &val) {fn(val); return *this;}
+
+ #define OPERATOR_WRITE(type, fn) \
+ LMessage& operator<<(type &val) {fn(val); return *this;}
+
+
+ // Message status flags.
+ #define LMSTAT_READOVERFLOW (1<<0)
+ #define LMSTAT_WRITEOVERFLOW (1<<1)
+
+
+ class LMessage
+ {
+ public:
+
+ // Call this to free the message.
+ virtual DRESULT Release()=0;
+
+ // Helpers..
+ DBYTE ReadByte() {DBYTE temp; ReadByteFL(temp); return temp;}
+ D_WORD ReadWord() {D_WORD temp; ReadWordFL(temp); return temp;}
+ DDWORD ReadDWord() {DDWORD temp; ReadDWordFL(temp); return temp;}
+ float ReadFloat() {float temp; ReadFloatFL(temp); return temp;}
+ HSTRING ReadHString() {HSTRING temp; ReadHStringFL(temp); return temp;}
+ HOBJECT ReadObject() {HOBJECT temp; ReadObjectFL(temp); return temp;}
+ DVector ReadVector() {DVector temp; ReadVectorFL(temp); return temp;}
+ DVector ReadCompVector(){DVector temp; ReadCompVectorFL(temp); return temp;}
+ DVector ReadCompPos() {DVector temp; ReadCompPosFL(temp); return temp;}
+ DRotation ReadRotation() {DRotation temp; ReadRotationFL(temp); return temp;}
+ DRotation ReadCompRotation() {DRotation temp; ReadCompRotationFL(temp); return temp;}
+ LMessage* ReadMessage() {LMessage *pMsg; ReadMessageFL(pMsg); return pMsg;}
+ OPERATOR_READ(DBYTE, ReadByteFL)
+ OPERATOR_READ(D_WORD, ReadWordFL)
+ OPERATOR_READ(DDWORD, ReadDWordFL)
+ OPERATOR_READ(float, ReadFloatFL)
+ OPERATOR_READ(DVector, ReadVectorFL)
+ OPERATOR_READ(DRotation, ReadRotationFL)
+ OPERATOR_READ(HOBJECT, ReadObjectFL)
+ OPERATOR_WRITE(DBYTE, WriteByte)
+ OPERATOR_WRITE(D_WORD, WriteWord)
+ OPERATOR_WRITE(DDWORD, WriteDWord)
+ OPERATOR_WRITE(float, WriteFloat)
+ OPERATOR_WRITE(DVector, WriteVector)
+ OPERATOR_WRITE(DRotation, WriteRotation)
+ OPERATOR_WRITE(HOBJECT, WriteObject)
+
+ // FL means full.. most people will use the simpler versions above.
+ virtual DRESULT ReadByteFL(DBYTE &val)=0;
+ virtual DRESULT ReadWordFL(D_WORD &val)=0;
+ virtual DRESULT ReadDWordFL(DDWORD &val)=0;
+ virtual DRESULT ReadFloatFL(float &val)=0;
+ virtual DRESULT ReadStringFL(char *pData, DDWORD maxBytes)=0;
+ virtual DRESULT ReadHStringFL(HSTRING &hString)=0;
+ virtual DRESULT ReadRawFL(void *pData, DDWORD len)=0;
+ virtual DRESULT ReadVectorFL(DVector &vec)=0;
+ virtual DRESULT ReadCompVectorFL(DVector &vec)=0;
+ virtual DRESULT ReadCompPosFL(DVector &vec)=0;
+ virtual DRESULT ReadRotationFL(DRotation &rot)=0;
+ virtual DRESULT ReadCompRotationFL(DRotation &rot)=0;
+ virtual DRESULT ReadMessageFL(LMessage* &pMsg)=0;
+
+ // Note: this could very well return NULL if the object sent doesn't still exist.
+ // The object will NOT be there if you send a message with the object in it right
+ // after creating it. The server must process at least one update on an object
+ // before you can send it to the client.
+ virtual DRESULT ReadObjectFL(HOBJECT &hObj)=0;
+
+ virtual DRESULT WriteByte(DBYTE val)=0;
+ virtual DRESULT WriteWord(D_WORD val)=0;
+ virtual DRESULT WriteDWord(DDWORD val)=0;
+ virtual DRESULT WriteFloat(float val)=0;
+ virtual DRESULT WriteString(char *pData)=0;
+ virtual DRESULT WriteVector(DVector &vec)=0; // 12 bytes
+ virtual DRESULT WriteCompVector(DVector &vec)=0; // 9 bytes
+ virtual DRESULT WriteCompPos(DVector &vec)=0; // 6 bytes
+ virtual DRESULT WriteRotation(DRotation &rot)=0; // 16 bytes
+ virtual DRESULT WriteCompRotation(DRotation &rot)=0; // 3-6 bytes
+ virtual DRESULT WriteRaw(void *pData, DDWORD len)=0;
+ virtual DRESULT WriteMessage(LMessage &msg)=0;
+ virtual DRESULT WriteHString(HSTRING hString)=0;
+
+ // Write a string formatted from a string resource (from cres.dll or sres.dll).
+ virtual DRESULT WriteHStringFormatted(int messageCode, ...)=0;
+ virtual DRESULT WriteHStringArgList(int messageCode, va_list *pList)=0;
+
+ // Some notes about this function. This only works for objects created by the
+ // server. If you put an object in here created by the client, then the receiver
+ // will get NULL out. If the object has been removed on the server before this
+ // message gets read, the receiver will wind up with a different object handle,
+ // so be careful!
+ virtual DRESULT WriteObject(HOBJECT hObj)=0;
+
+ // Reset the read position. It automatically resets when you read to the end of the
+ // message.
+ virtual DRESULT ResetPos()=0;
+
+ // As you read/write to the message, you can check these flags to see if there was an error.
+ // flags will be filled in with a combination of the LMSTAT_ flags above.
+ virtual DRESULT GetStatus(DDWORD &flags)=0;
+ };
+
+
+#endif
+
+
+
+
+
+
+
+
diff --git a/AppHeaders/matrix_ops.h b/AppHeaders/matrix_ops.h
new file mode 100644
index 0000000..5954717
--- /dev/null
+++ b/AppHeaders/matrix_ops.h
@@ -0,0 +1,219 @@
+
+// Defines all the matrix operations.
+
+#ifndef __MATRIX_OPS_H__
+#define __MATRIX_OPS_H__
+
+
+ // Matrices are indexed by (y,x), so a translation matrix looks like:
+ // 1 0 0 tx (tx is in m[0][3])
+ // 0 1 0 ty (ty is in m[1][3])
+ // 0 0 1 tz (tz is in m[2][3])
+ // 0 0 0 1
+
+ typedef struct
+ {
+ float m[4][4];
+ } DMatrix;
+
+
+
+ INLINE_FN void Mat_Identity(DMatrix *pMat)
+ {
+ MAT_SET(*pMat,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+
+ INLINE_FN void Mat_GetBasisVectors(DMatrix *pMat, DVector *pRight, DVector *pUp, DVector *pForward)
+ {
+ pRight->x = pMat->m[0][0];
+ pRight->y = pMat->m[1][0];
+ pRight->z = pMat->m[2][0];
+
+ pUp->x = pMat->m[0][1];
+ pUp->y = pMat->m[1][1];
+ pUp->z = pMat->m[2][1];
+
+ pForward->x = pMat->m[0][2];
+ pForward->y = pMat->m[1][2];
+ pForward->z = pMat->m[2][2];
+ }
+
+
+ INLINE_FN void Mat_SetBasisVectors(DMatrix *pMat, DVector *pRight, DVector *pUp, DVector *pForward)
+ {
+ MAT_SET(*pMat,
+ pRight->x, pUp->x, pForward->x, 0.0f,
+ pRight->y, pUp->y, pForward->y, 0.0f,
+ pRight->z, pUp->z, pForward->z, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+
+ // Transpose the upper left 3x3.
+ INLINE_FN void MatTranspose3x3(DMatrix *pMat)
+ {
+ float temp;
+ float *d = (float*)pMat->m;
+
+ temp = d[1]; d[1] = d[4]; d[4] = temp;
+ temp = d[2]; d[2] = d[8]; d[8] = temp;
+ temp = d[9]; d[9] = d[6]; d[6] = temp;
+ }
+
+
+ // Mat3 = Mat1 * Mat2
+ #define M1 pMat1->m
+ #define M2 pMat2->m
+
+ INLINE_FN void MatMul(DMatrix *pDest, DMatrix *pMat1, DMatrix *pMat2)
+ {
+ pDest->m[0][0] = M1[0][0]*M2[0][0] + M1[0][1]*M2[1][0] + M1[0][2]*M2[2][0] + M1[0][3]*M2[3][0];
+ pDest->m[1][0] = M1[1][0]*M2[0][0] + M1[1][1]*M2[1][0] + M1[1][2]*M2[2][0] + M1[1][3]*M2[3][0];
+ pDest->m[2][0] = M1[2][0]*M2[0][0] + M1[2][1]*M2[1][0] + M1[2][2]*M2[2][0] + M1[2][3]*M2[3][0];
+ pDest->m[3][0] = M1[3][0]*M2[0][0] + M1[3][1]*M2[1][0] + M1[3][2]*M2[2][0] + M1[3][3]*M2[3][0];
+
+ pDest->m[0][1] = M1[0][0]*M2[0][1] + M1[0][1]*M2[1][1] + M1[0][2]*M2[2][1] + M1[0][3]*M2[3][1];
+ pDest->m[1][1] = M1[1][0]*M2[0][1] + M1[1][1]*M2[1][1] + M1[1][2]*M2[2][1] + M1[1][3]*M2[3][1];
+ pDest->m[2][1] = M1[2][0]*M2[0][1] + M1[2][1]*M2[1][1] + M1[2][2]*M2[2][1] + M1[2][3]*M2[3][1];
+ pDest->m[3][1] = M1[3][0]*M2[0][1] + M1[3][1]*M2[1][1] + M1[3][2]*M2[2][1] + M1[3][3]*M2[3][1];
+
+ pDest->m[0][2] = M1[0][0]*M2[0][2] + M1[0][1]*M2[1][2] + M1[0][2]*M2[2][2] + M1[0][3]*M2[3][2];
+ pDest->m[1][2] = M1[1][0]*M2[0][2] + M1[1][1]*M2[1][2] + M1[1][2]*M2[2][2] + M1[1][3]*M2[3][2];
+ pDest->m[2][2] = M1[2][0]*M2[0][2] + M1[2][1]*M2[1][2] + M1[2][2]*M2[2][2] + M1[2][3]*M2[3][2];
+ pDest->m[3][2] = M1[3][0]*M2[0][2] + M1[3][1]*M2[1][2] + M1[3][2]*M2[2][2] + M1[3][3]*M2[3][2];
+
+ pDest->m[0][3] = M1[0][0]*M2[0][3] + M1[0][1]*M2[1][3] + M1[0][2]*M2[2][3] + M1[0][3]*M2[3][3];
+ pDest->m[1][3] = M1[1][0]*M2[0][3] + M1[1][1]*M2[1][3] + M1[1][2]*M2[2][3] + M1[1][3]*M2[3][3];
+ pDest->m[2][3] = M1[2][0]*M2[0][3] + M1[2][1]*M2[1][3] + M1[2][2]*M2[2][3] + M1[2][3]*M2[3][3];
+ pDest->m[3][3] = M1[3][0]*M2[0][3] + M1[3][1]*M2[1][3] + M1[3][2]*M2[2][3] + M1[3][3]*M2[3][3];
+ }
+
+
+ // Mat2 = Mat1 * Mat2
+ INLINE_FN void MatMul_InPlace(DMatrix *pMat1, DMatrix *pMat2)
+ {
+ DMatrix temp;
+ MatMul(&temp, pMat1, pMat2);
+ MAT_COPY(*pMat2, temp);
+ }
+
+
+ // Non-homogenous matrix multiply.
+ INLINE_FN void MatVMul(DVector *pDest, DMatrix *pMat, DVector *pSrc)
+ {
+ pDest->x = pMat->m[0][0]*pSrc->x + pMat->m[0][1]*pSrc->y + pMat->m[0][2]*pSrc->z + pMat->m[0][3];
+ pDest->y = pMat->m[1][0]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[1][2]*pSrc->z + pMat->m[1][3];
+ pDest->z = pMat->m[2][0]*pSrc->x + pMat->m[2][1]*pSrc->y + pMat->m[2][2]*pSrc->z + pMat->m[2][3];
+ }
+
+ INLINE_FN void MatVMul_InPlace(DMatrix *pMat, DVector *pSrc)
+ {
+ DVector temp;
+ MatVMul(&temp, pMat, pSrc);
+ VEC_COPY(*pSrc, temp);
+ }
+
+
+ // Matrix multiply with the homogenous divide.
+ INLINE_FN float MatVMul_H(DVector *pDest, DMatrix *pMat, DVector *pSrc)
+ {
+ float one_over_w = 1.0f / (pMat->m[3][0]*pSrc->x + pMat->m[3][1]*pSrc->y + pMat->m[3][2]*pSrc->z + pMat->m[3][3]);
+
+ pDest->x = one_over_w * (pMat->m[0][0]*pSrc->x + pMat->m[0][1]*pSrc->y + pMat->m[0][2]*pSrc->z + pMat->m[0][3]);
+ pDest->y = one_over_w * (pMat->m[1][0]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[1][2]*pSrc->z + pMat->m[1][3]);
+ pDest->z = one_over_w * (pMat->m[2][0]*pSrc->x + pMat->m[2][1]*pSrc->y + pMat->m[2][2]*pSrc->z + pMat->m[2][3]);
+
+ return one_over_w;
+ }
+
+ INLINE_FN float MatVMul_InPlace_H(DMatrix *pMat, DVector *pSrc)
+ {
+ float one_over_w = 1.0f / (pMat->m[3][0]*pSrc->x + pMat->m[3][1]*pSrc->y + pMat->m[3][2]*pSrc->z + pMat->m[3][3]);
+ DVector temp;
+
+ temp.x = one_over_w * (pMat->m[0][0]*pSrc->x + pMat->m[0][1]*pSrc->y + pMat->m[0][2]*pSrc->z + pMat->m[0][3]);
+ temp.y = one_over_w * (pMat->m[1][0]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[1][2]*pSrc->z + pMat->m[1][3]);
+ temp.z = one_over_w * (pMat->m[2][0]*pSrc->x + pMat->m[2][1]*pSrc->y + pMat->m[2][2]*pSrc->z + pMat->m[2][3]);
+
+ VEC_COPY(*pSrc, temp);
+ return one_over_w;
+ }
+
+
+ // Matrix multiply using upper left 3x3.
+ INLINE_FN void MatVMul_3x3(DVector *pDest, DMatrix *pMat, DVector *pSrc)
+ {
+ pDest->x = pMat->m[0][0]*pSrc->x + pMat->m[0][1]*pSrc->y + pMat->m[0][2]*pSrc->z;
+ pDest->y = pMat->m[1][0]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[1][2]*pSrc->z;
+ pDest->z = pMat->m[2][0]*pSrc->x + pMat->m[2][1]*pSrc->y + pMat->m[2][2]*pSrc->z;
+ }
+
+ INLINE_FN void MatVMul_InPlace_3x3(DMatrix *pMat, DVector *pSrc)
+ {
+ DVector temp;
+ MatVMul_3x3(&temp, pMat, pSrc);
+ VEC_COPY(*pSrc, temp);
+ }
+
+
+ // Transposed matrix multiply (using upper left 3x3).
+ INLINE_FN void MatVMul_Transposed3x3(DVector *pDest, DMatrix *pMat, DVector *pSrc)
+ {
+ pDest->x = pMat->m[0][0]*pSrc->x + pMat->m[1][0]*pSrc->y + pMat->m[2][0]*pSrc->z;
+ pDest->y = pMat->m[0][1]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[2][1]*pSrc->z;
+ pDest->z = pMat->m[0][2]*pSrc->x + pMat->m[1][2]*pSrc->y + pMat->m[2][2]*pSrc->z;
+ }
+
+ INLINE_FN void MatVMul_InPlace_Transposed3x3(DMatrix *pMat, DVector *pSrc)
+ {
+ DVector temp;
+
+ temp.x = pMat->m[0][0]*pSrc->x + pMat->m[1][0]*pSrc->y + pMat->m[2][0]*pSrc->z;
+ temp.y = pMat->m[0][1]*pSrc->x + pMat->m[1][1]*pSrc->y + pMat->m[2][1]*pSrc->z;
+ temp.z = pMat->m[0][2]*pSrc->x + pMat->m[1][2]*pSrc->y + pMat->m[2][2]*pSrc->z;
+
+ VEC_COPY(*pSrc, temp);
+ }
+
+
+ // Set the matrix up to rotate 'amount' radians around the given axis.
+ INLINE_FN void Mat_SetupRot(DMatrix *pMat, DVector *pVec, float amount)
+ {
+ float s, c, t;
+ float tx, ty, tz;
+ float sx, sy, sz;
+
+ s = (float)sin(amount);
+ c = (float)cos(amount);
+ t = 1.0f - c;
+
+ tx = t * pVec->x; ty = t * pVec->y; tz = t * pVec->z;
+ sx = s * pVec->x; sy = s * pVec->y; sz = s * pVec->z;
+
+ pMat->m[0][0] = tx*pVec->x + c;
+ pMat->m[1][0] = tx*pVec->y + sz;
+ pMat->m[2][0] = tx*pVec->z - sy;
+
+ pMat->m[0][1] = tx*pVec->y - sz;
+ pMat->m[1][1] = ty*pVec->y + c;
+ pMat->m[2][1] = ty*pVec->z + sx;
+
+ pMat->m[0][2] = tx*pVec->z + sy;
+ pMat->m[1][2] = ty*pVec->z - sx;
+ pMat->m[2][2] = tz*pVec->z + c;
+
+ // Make the unfulled parts identity.
+ pMat->m[3][0] = 0.0f; pMat->m[3][1] = 0.0f; pMat->m[3][2] = 0.0f;
+ pMat->m[0][3] = 0.0f; pMat->m[1][3] = 0.0f; pMat->m[2][3] = 0.0f;
+ pMat->m[3][3] = 1.0f;
+ }
+
+
+#endif
+
+
diff --git a/AppHeaders/physics_lt.h b/AppHeaders/physics_lt.h
new file mode 100644
index 0000000..6f0b980
--- /dev/null
+++ b/AppHeaders/physics_lt.h
@@ -0,0 +1,99 @@
+
+// This interface implements physics functionality.
+
+#ifndef __PHYSICS_LT_H__
+#define __PHYSICS_LT_H__
+
+
+ // Sets the dims as large as it can by testing to see what's around the object.
+ // The object will get touch notifications if it hits anything while resizing.
+ #define SETDIMS_PUSHOBJECTS (1<<0)
+
+
+ // Teleport the object to its destination.
+ #define MOVEOBJECT_TELEPORT (1<<0)
+
+
+ class MoveInfo
+ {
+ public:
+ HOBJECT m_hObject;
+ float m_dt;
+ DVector m_Offset;
+ };
+
+
+ class PhysicsLT
+ {
+ public:
+
+ // Get/Set friction coefficient.
+ virtual DRESULT GetFrictionCoefficient(HOBJECT hObj, float &coeff);
+ virtual DRESULT SetFrictionCoefficient(HOBJECT hObj, float coeff);
+
+ // Get/set force ignore limit.
+ virtual DRESULT GetForceIgnoreLimit(HOBJECT hObj, float &limit);
+ virtual DRESULT SetForceIgnoreLimit(HOBJECT hObj, float limit);
+
+ // Get/Set acceleration and velocity
+ virtual DRESULT GetVelocity(HOBJECT hObj, DVector *pVel);
+ virtual DRESULT SetVelocity(HOBJECT hObj, DVector *pVel)=0;
+
+ virtual DRESULT GetAcceleration(HOBJECT hObj, DVector *pAccel);
+ virtual DRESULT SetAcceleration(HOBJECT hObj, DVector *pAccel)=0;
+
+ // Get/Set an object's mass (default is 30).
+ virtual DRESULT GetObjectMass(HOBJECT hObj, float &mass);
+ virtual DRESULT SetObjectMass(HOBJECT hObj, float mass);
+
+ // Get the object's current dimensions.
+ virtual DRESULT GetObjectDims(HOBJECT hObj, DVector *pNewDims);
+
+ // Changes the object's dimensions without pushing against objects and world.
+ // Flags is a combination of SETDIMS_ flags above.
+ virtual DRESULT SetObjectDims(HOBJECT hObj, DVector *pNewDims, DDWORD flags)=0;
+
+ // This function moves an object, colliding/pushing/crushing objects
+ // in its way (if it's solid..) Flags is a combination of MOVEOBJECT_ flags.
+ virtual DRESULT MoveObject(HOBJECT hObj, DVector *pPos, DDWORD flags)=0;
+
+ // Find out what the object is standing on.
+ virtual DRESULT GetStandingOn(HOBJECT hObj, CollisionInfo *pInfo);
+
+ // Get the world object.
+ virtual DRESULT GetWorldObject(HOBJECT *hObj)=0;
+
+ // Get/set global force. This is an acceleration applied to all objects
+ // when they move. Default is (0,-2000,0) which simulates gravity.
+ virtual DRESULT GetGlobalForce(DVector &vec)=0;
+ virtual DRESULT SetGlobalForce(DVector &vec)=0;
+
+ protected:
+ ClientServerType m_ClientServerType; // Tells if this is on the client or server.
+ };
+
+
+ // Client-specific physics stuff.
+ class CPhysicsLT : public PhysicsLT
+ {
+ public:
+ // Updates the object's movement using its velocity, acceleration, and the
+ // time delta passed in (usually the frame time). Fills in m_Offset with the
+ // position delta you should apply.
+ virtual DRESULT UpdateMovement(MoveInfo *pInfo)=0;
+
+ // Move the specified object but only test for collisions/pushing on
+ // the objects specified. It'll carry things standing on it.
+ virtual DRESULT MovePushObjects(HOBJECT hToMove, DVector &newPos,
+ HOBJECT *hPushObjects, DDWORD nPushObjects)=0;
+
+ // Rotate the specified object but only test for collisions/pushing on
+ // the objects specified. It'll carry things standing on it.
+ // This only works on world models.
+ virtual DRESULT RotatePushObjects(HOBJECT hToMove, DRotation &newRot,
+ HOBJECT *hPushObjects, DDWORD nPushObjects)=0;
+ };
+
+
+#endif
+
diff --git a/AppHeaders/server_de.h b/AppHeaders/server_de.h
new file mode 100644
index 0000000..f8b1853
--- /dev/null
+++ b/AppHeaders/server_de.h
@@ -0,0 +1,932 @@
+
+// server_de defines the ServerDE structure, which consists of all the
+// server-side DirectEngine functionality.
+
+#ifndef __SERVER_DE_H__
+#define __SERVER_DE_H__
+
+
+ #include "basedefs_de.h"
+ #include "serverobj_de.h"
+ #include "common_de.h"
+ #include "CSBase.h"
+
+
+ DEFINE_HANDLE_TYPE(HCONVAR);
+ DEFINE_HANDLE_TYPE(HCLIENTREF);
+
+
+ // Load world flags.
+ #define LOADWORLD_LOADWORLDOBJECTS (1<<0) // Load objects from the world file?
+ #define LOADWORLD_RUNWORLD (1<<1) // Start running world immediately?
+ #define LOADWORLD_NORELOADGEOMETRY (1<<2) // Don't reload geometry if the world filename
+ // is the same as the currently loaded one.
+
+ // ---------------------------------------------------------------------- //
+ // Load/Save objects flags.
+ // ---------------------------------------------------------------------- //
+
+ #define RESTOREOBJECTS_RESTORETIME 1 // Restore time information?
+
+ #define SAVEOBJECTS_SAVEGAMECONSOLE 1 // Save the game console state?
+ #define SAVEOBJECTS_SAVEPORTALS 2 // Save the portal states?
+
+
+ // ---------------------------------------------------------------------- //
+ // Client info flags.
+ //
+ // CIF_LOCAL and CIF_PLAYBACK are not settable with SetClientInfoFlags.
+ // ---------------------------------------------------------------------- //
+
+ #define CIF_LOCAL (1<<0) // Client is local (non-network) connection.
+ #define CIF_PLAYBACK (1<<1) // Virtual client from a demo playback.
+ #define CIF_FULLRES (1<<2) // Client object is sent with full position resolution.
+ #define CIF_SENDCOBJROTATION (1<<3) // Client object rotations are sent to client.
+ #define CIF_FORCENEXTUPDATE (1<<4) // Force the server to update the client on the state
+ // of the world as soon as it can. In multiplayer
+ // games, it doesn't update the clients every frame
+ // and this can be used if you send a message to the client
+ // that needs to arrive in sync with object changes (like
+ // animation changes).
+
+
+ // ---------------------------------------------------------------------- //
+ // Object states.
+ //
+ // OBJSTATE_INACTIVE and OBJSTATE_INACTIVE_TOUCH override the effect of
+ // PingObjects. OBJSTATE_ACTIVE clears the effect of OBJSTATE_INACTIVE
+ // or OBJSTATE_INACTIVE_TOUCH, but the object can be autodeactivated.
+ // ---------------------------------------------------------------------- //
+
+
+ #define OBJSTATE_ACTIVE 0 // Normal healthy object.
+ #define OBJSTATE_INACTIVE 1 // Inactive (no updates, physics, or touch notifies).
+ #define OBJSTATE_INACTIVE_TOUCH 2 // Inactive, but gets touch notifies.
+ #define OBJSTATE_AUTODEACTIVATE_NOW 3 // Autodeactivate now, can reactivate thru PingObjects call.
+
+
+
+ // ---------------------------------------------------------------------- //
+ // Server state flags.
+ // ---------------------------------------------------------------------- //
+
+ #define SS_PAUSED (1<<0) // Server is paused.
+ #define SS_DEMOPLAYBACK (1<<1) // We're running in 'demo playback' mode (read only).
+ #define SS_CACHING (1<<2) // Server can pre-cache files.
+ #define SS_LASTFLAG SS_DEMOPLAYBACK
+
+
+ // ---------------------------------------------------------------------- //
+ // Object lists.
+ // ---------------------------------------------------------------------- //
+
+ typedef struct ObjectLink_t
+ {
+ HOBJECT m_hObject;
+ struct ObjectLink_t *m_pNext;
+ } ObjectLink;
+
+ typedef struct ObjectList_t
+ {
+ ObjectLink *m_pFirstLink;
+ int m_nInList;
+ } ObjectList;
+
+
+
+
+ // ---------------------------------------------------------------------- //
+ // GenericProp -
+ // Here's a list of which property types map to which variables:
+ // PT_STRING - m_Vec and m_Color if it's formatted like '1 2 3', m_String, m_Long, m_Float, m_Bool.
+ // - if this is 'true' or 'false', it'll set m_Long, m_Float, and m_Bool to 0 or 1.
+
+ // PT_VECTOR - m_Vec, m_String ('1 2 3')
+ // PT_COLOR - m_Color, m_String ('1 2 3')
+ // PT_REAL - m_String, m_Long, m_Float, m_Bool
+ // PT_FLAGS - m_String, m_Long, m_Float, m_Bool
+ // PT_BOOL - m_String, m_Long, m_Float, m_Bool
+ // PT_LONGINT - m_String, m_Long, m_Float, m_Bool
+ // PT_ROTATION - m_Rotation and m_Vec (with euler rotation).
+ // ---------------------------------------------------------------------- //
+
+ #define MAX_GP_STRING_LEN 200
+
+ typedef struct GenericProp_t
+ {
+ DVector m_Vec;
+ DVector m_Color;
+
+ char m_String[MAX_GP_STRING_LEN+1];
+ DRotation m_Rotation;
+ long m_Long;
+ float m_Float;
+ DBOOL m_Bool;
+ } GenericProp;
+
+
+
+
+ class PhysicsLT;
+
+
+ // ---------------------------------------------------------------------- //
+ // CServerDE interface. This is your interface to most DirectEngine
+ // functionality.
+ // ---------------------------------------------------------------------- //
+
+ class ServerDE : public CSBase
+ {
+ friend class CServerMgr;
+
+ protected:
+
+ virtual ~ServerDE() {}
+
+
+ public:
+ // Access to the smaller interfaces.
+
+ CommonLT* Common() {return m_pCommonLT;}
+ PhysicsLT* Physics() {return m_pPhysicsLT;}
+
+
+ // Main functions.
+
+ // Gives you access to the m_pGameInfo from the StartGameRequest structure.
+ // Note: this is a copy of the data and the pointer filled in can be NULL
+ // if there is no game info data.
+ DRESULT (*GetGameInfo)(void **ppData, DDWORD *pLen);
+
+ // Returns DNULL if the class doesn't exist.
+ HCLASS (*GetClass)(char *pName);
+
+ // Get a class's static object. Returns DE_NOTFOUND if the server
+ // doesn't have a static object of this class.
+ DRESULT (*GetStaticObject)(HCLASS hClass, HOBJECT *obj);
+
+ // OBSOLETE. Use PhysicsLT.
+ virtual HOBJECT GetWorldObject()=0;
+
+ // Get an object's class.
+ HCLASS (*GetObjectClass)(HOBJECT hObject);
+
+ // Tells if hClass is the class of hTest (or is derived from hTest).
+ // If you pass in DNULL for hTest (like if GetClass returns DNULL in
+ // IsKindOf(hClass, GetClass("TestClass"))), it will return FALSE.
+ DBOOL (*IsKindOf)(HCLASS hClass, HCLASS hTest);
+
+
+ // Creates an object using the object's default object type.
+ LPBASECLASS (*CreateObject)(HCLASS hClass, struct ObjectCreateStruct_t *pStruct);
+
+ // Creates an object using string to specify properties.
+ LPBASECLASS (*CreateObjectProps)(HCLASS hClass, struct ObjectCreateStruct_t *pStruct, char *pszProps );
+
+ // Remove the object from the world. Note: the object won't be removed
+ // or deleted until the end of the frame.
+ void (*RemoveObject)(HOBJECT hObject);
+
+
+ // Returns the current time, in seconds, since the server started up.
+ DFLOAT (*GetTime)();
+
+ // Returns the time since the last server shell update.
+ DFLOAT (*GetFrameTime)();
+
+
+ // OBSOLETE. Use PhysicsLT functions.
+ virtual DRESULT GetGlobalForce(DVector *pVec)=0;
+ virtual DRESULT SetGlobalForce(DVector *pVec)=0;
+
+
+ // Server state flags. (Combination of the SS_ flags above).
+ // SetServerFlags returns the new flags (some may not be accepted).
+ DDWORD (*GetServerFlags)();
+ DDWORD (*SetServerFlags)(DDWORD flags);
+
+ // Cache in the given file. Only call this from ServerShell::CacheFiles.
+ // fileType is one of the FT_ defines in de_codes.
+ // Returns DE_NOTFOUND if it can't find the file.
+ DRESULT (*CacheFile)(DDWORD fileType, char *pFilename);
+
+
+ // Helpers..
+
+ // Use this to iterate over all the polies in the world.
+ // Returns DE_FINISHED when there are no more polies to look at.
+ // Returns LT_NOTINITIALIZED if there is no world loaded.
+ // Iterate like this:
+ // HPOLY hPoly = INVALID_HPOLY;
+ // while(pServerDE->GetNextPoly(&hPoly) == LT_OK)
+ // {
+ // ... do something with hPoly ...
+ // }
+ DRESULT (*GetNextPoly)(HPOLY *hPoly);
+
+ // Use these to time sections of code. Timing is done in microseconds
+ // (1,000,000 counts per second).
+ void (*StartCounter)(struct DCounter_t *pCounter);
+ DDWORD (*EndCounter)(struct DCounter_t *pCounter);
+
+ // Returns a random number in the given range.
+ DFLOAT (*Random)(DFLOAT min, DFLOAT max);
+
+ // Returns an integer number in the given range.
+ int (*IntRandom)(int min, int max);
+
+ // Returns a number from 0 to scale.
+ DFLOAT (*RandomScale)(DFLOAT scale);
+
+ // Only use this for debugging.. sends an STC_BPRINT message
+ // with the string in it.
+ void (*BPrint)(char *pMsg, ...);
+
+ // A better BPrint.. prints right to the console (doesn't do any network stuff) and
+ // doesn't matter if you're connected yet.
+ void (*CPrint)(char *pMsg, ...);
+
+ // Used to output a TRACE message to the Debug Output window. Newlines must be explicitly used.
+ void (*DebugOut)( char *pMsg, ... );
+
+ // Get/Set the sky definition.
+ DRESULT (*GetSkyDef)(struct SkyDef_t *pDef);
+ DRESULT (*SetSkyDef)(struct SkyDef_t *pDef);
+
+ // Add/Remove objects from the sky list.
+ // Each object should have a unique index.
+ DRESULT (*AddObjectToSky)(HOBJECT hObj, DDWORD index);
+ DRESULT (*RemoveObjectFromSky)(HOBJECT hObj);
+
+
+ // String functions. Strings are reference counted objects that cannot
+ // be manipulated. When you create one with FormatString or CreateString,
+ // the reference count is 1. When you copy a string with CopyString, the
+ // reference count is incremented. When you free one with FreeString,
+ // it decrements the reference count.. when the reference count goes to
+ // zero, it deletes the string. If you forget to free up any strings,
+ // LithTech will spit out a message telling you about it..
+
+ // In Windows, messageCode comes from your resource DLL. The messages
+ // need to be formatted with %1!s! %2!s! (the number is the argument
+ // number and the !s! says its a string). You can also use !f! and !d!
+ // for floating point and whole number.
+ HSTRING (*FormatString)(int messageCode, ...);
+
+ // Copy a string.. much more efficient than CreateString().
+ HSTRING (*CopyString)(HSTRING hString);
+ HSTRING (*CreateString)(char *pString);
+ void (*FreeString)(HSTRING hString);
+
+ DBOOL (*CompareStrings)(HSTRING hString1, HSTRING hString2);
+ DBOOL (*CompareStringsUpper)(HSTRING hString1, HSTRING hString2);
+
+ // Get the string's data.. you really should only use this for strings
+ // that you stored off and want to pass to the engine for a filename
+ // or something.. Most strings could be in some format other than ANSI.
+ char* (*GetStringData)(HSTRING hString);
+
+
+ // World control.
+
+ // Portal flags are a combination of PORTAL_ flags in de_codes.
+ // Returns DE_OK, DE_NOTFOUND, or DE_NOTINWORLD. This is
+ // case sensitive.
+ DRESULT (*GetPortalFlags)(char *pPortalName, DDWORD *pFlags);
+ DRESULT (*SetPortalFlags)(char *pPortalName, DDWORD flags);
+
+ // Intersect a line segment.. (used to be raycast, but line segments are WAY faster).
+ // Returns TRUE and fills in pInfo if it hit something.
+ DBOOL (*IntersectSegment)(IntersectQuery *pQuery, IntersectInfo *pInfo);
+
+ // Same as IntersectSegment, except for it casts a ray from pQuery->m_From
+ // in the direction of pQuery->m_Dir.
+ DBOOL (*CastRay)(IntersectQuery *pQuery, IntersectInfo *pInfo);
+
+ ///////////////// NOT IMPLEMENTED YET /////////////////
+ // Find out what's at a given point (is it inside the world, outside, what
+ // area brushes is it inside..) You must give back the list to the engine
+ // with RelinquishList()!
+ ObjectList* (*GetPointAreas)(DVector *pPoint);
+
+ ///////////////// NOT IMPLEMENTED YET /////////////////
+ // Find the objects intersecting this box.
+ ObjectList* (*GetBoxIntersecters)(DVector *pMin, DVector *pMax);
+
+ // Get the shade (RGB, 0-255) at the point you specify.
+ // Returns DFALSE if the point is outside the world.
+ DBOOL (*GetPointShade)(DVector *pPoint, DVector *pColor);
+
+ // Gets all the objects with the given name.
+ // Don't forget to relinquish the list you get!
+ ObjectList* (*FindNamedObjects)(char *pName);
+
+ // Find all the objects touching the given sphere.
+ // Don't forget to relinquish the list you get!
+ // Be VERY careful of using a large radius. This function can take
+ // tons of cycles if the radius is too large.
+ ObjectList* (*FindObjectsTouchingSphere)(DVector *pPosition, float radius);
+
+ // Finds objects touching the cone you specify. This will provide a slight
+ // overestimation of the cone you specify. This can be much faster than
+ // FindObjectsTouchingSphere, depending on how small the angle is.
+ ObjectList* (*FindObjectsTouchingCone)(DVector *pPos, DVector *pDir, float angle, float dist);
+
+ // Any time the engine gives you a list, you must 'give it back' with this,
+ // or else you'll have tons of memory leaks.
+ void (*RelinquishList)(ObjectList *pList);
+
+ // Get the bounding box for the current world.
+ virtual DRESULT GetWorldBox(DVector &min, DVector &max)=0;
+
+
+ // Object list management.
+
+ // Allocate a list (free it with RelinquishList).
+ ObjectList* (*CreateObjectList)();
+
+ // Add objects to a list.
+ ObjectLink* (*AddObjectToList)(ObjectList *pList, HOBJECT hObj);
+
+ // Remove an object from the list given the handle.
+ // Note: DirectEngine will just do a search over all the objects in the
+ // list for this, so be warned.
+ void (*RemoveObjectFromList)(ObjectList *pList, HOBJECT hObj);
+
+
+
+ // OBSOLETE messaging functions. Use CommonLT::CreateMessage, LMessage::Release,
+ // and ServerDE::SendToX.
+
+ virtual HMESSAGEWRITE StartSpecialEffectMessage(LPBASECLASS pObject)=0;
+ virtual HMESSAGEWRITE StartInstantSpecialEffectMessage(DVector *pPos)=0;
+ virtual HMESSAGEWRITE StartMessageToObject(LPBASECLASS pSender, HOBJECT hSendTo, DDWORD messageID)=0;
+ virtual DRESULT StartMessageToServer(LPBASECLASS pSender, DDWORD messageID, HMESSAGEWRITE *hWrite)=0;
+ virtual HMESSAGEWRITE StartMessage(HCLIENT hSendTo, DBYTE messageID)=0;
+ virtual DRESULT EndMessage2(HMESSAGEWRITE hMessage, DDWORD flags)=0;
+ virtual DRESULT EndMessage(HMESSAGEWRITE hMessage)=0; // Just calls EndMessage2 with MESSAGE_GUARANTEED.
+
+
+ // NEW message functions. The main difference between these and the functions above is
+ // that these don't free the message for you so you can send it multiple times.
+
+ // Use this to setup a special effect message. If your object has
+ // a special effect message, the client shell's SpecialEffectNotify()
+ // will be called. An object can only have ONE special effect message.
+ // If the object already has a special effect message, then it
+ // clears out the current one.
+ virtual DRESULT SetObjectSFXMessage(HOBJECT hObject, LMessage &msg)=0;
+
+ // Send a message to an object. hSender can be NULL.
+ virtual DRESULT SendToObject(LMessage &msg, DDWORD msgID, HOBJECT hSender, HOBJECT hSendTo, DDWORD flags)=0;
+
+ // Send the message to the server shell. hSender can be NULL.
+ virtual DRESULT SendToServer(LMessage &msg, DDWORD msgID, HOBJECT hSender, DDWORD flags)=0;
+
+ // Send the message to the client. If hSendTo is NULL, it sends to them all.
+ virtual DRESULT SendToClient(LMessage &msg, DBYTE msgID, HCLIENT hSendTo, DDWORD flags)=0;
+
+ // Sends the sfx message to all the clients who can see pos.
+ virtual DRESULT SendSFXMessage(LMessage &msg, DVector &pos, DDWORD flags)=0;
+
+
+ // Client Functions.
+
+ // Attach one client to another. This means that messages sent to hParent
+ // will also go to hClient, and hClient's client object will be reported
+ // as hParent's object. This is useful for demo playback when you want
+ // to watch another player's view.
+ DRESULT (*AttachClient)(HCLIENT hParent, HCLIENT hChild);
+
+ // Detach a client from its parent attachment.
+ DRESULT (*DetachClient)(HCLIENT hClient);
+
+ // Iterate over the clients. Pass in NULL to start. Returns NULL
+ // when there are no more.
+ HCLIENT (*GetNextClient)(HCLIENT hPrev);
+
+ // Iterate over the saved client references. These come from when
+ // a world is saved. Pass in DNULL to start. See the Client Functions
+ // section for the functions to look at these.
+ HCLIENTREF (*GetNextClientRef)(HCLIENTREF hRef);
+
+ // HCLIENTREFs are used for comparison to HCLIENTs.
+ DDWORD (*GetClientRefInfoFlags)(HCLIENTREF hClient);
+ DBOOL (*GetClientRefName)(HCLIENTREF hClient, char *pName, int maxLen);
+ HOBJECT (*GetClientRefObject)(HCLIENTREF hClient);
+
+ // Get a client's (unique) ID.
+ DDWORD (*GetClientID)(HCLIENT hClient);
+
+ // Get a client's ping time.
+ virtual DRESULT GetClientPing(HCLIENT hClient, float &ping)=0;
+
+ // Get a client's name.
+ DBOOL (*GetClientName)(HCLIENT hClient, char *pName, int maxLen);
+
+ // A combination of the CIF_ flags above.
+ void (*SetClientInfoFlags)(HCLIENT hClient, DDWORD dwClientFlags );
+ DDWORD (*GetClientInfoFlags)(HCLIENT hClient);
+
+ // User data for HCLIENTs.
+ void (*SetClientUserData)(HCLIENT hClient, void *pData);
+ void* (*GetClientUserData)(HCLIENT hClient);
+
+ // Kick a client off the server.
+ // OnRemoveClient will be called.
+ void (*KickClient)(HCLIENT hClient);
+
+ // Set where the client is seeing/hearing from. This controls what the
+ // server sends the client. You should set this every frame.
+ DRESULT (*SetClientViewPos)(HCLIENT hClient, DVector *pPos);
+
+
+ // The 'game console state'. This is a set of console variables and functions
+ // that is used internally by the application DLLs. The user can't access this
+ // at all. It's very useful for tracking global game variables and triggering
+ // them through game objects.
+
+ // Run a string through the game console. The syntax is the same as any
+ // other console string (semicolons separate commands, and new variable names
+ // create new HCONVARs).
+ void (*RunGameConString)(char *pString);
+
+ // Sets a console variable. Creates a new one if it doesn't exist.
+ void (*SetGameConVar)(char *pName, char *pVal);
+
+ // Get a handle to a console variable.
+ HCONVAR (*GetGameConVar)(char *pName);
+
+ // Get the floating point value of a console variable. If the hVar is
+ // NULL, then it returns 0.
+ float (*GetVarValueFloat)(HCONVAR hVar);
+
+ // Get the string value of a console variable. If the hVar is
+ // NULL, then it returns NULL.
+ char* (*GetVarValueString)(HCONVAR hVar);
+
+
+ // Helpers.
+
+ // These are used to get the property values from the world file.
+ // The property names are case sensitive. If the property doesn't exist,
+ // it will return DE_NOTFOUND.
+ DRESULT (*GetPropString)(char *pPropName, char *pRet, int maxLen);
+ DRESULT (*GetPropVector)(char *pPropName, DVector *pRet);
+ DRESULT (*GetPropColor)(char *pPropName, DVector *pRet);
+ DRESULT (*GetPropReal)(char *pPropName, float *pRet);
+ DRESULT (*GetPropFlags)(char *pPropName, DDWORD *pRet);
+ DRESULT (*GetPropBool)(char *pPropName, DBOOL *pRet);
+ DRESULT (*GetPropLongInt)(char *pPropName, long *pRet);
+ DRESULT (*GetPropRotation)(char *pPropName, DRotation *pRet);
+ DRESULT (*GetPropRotationEuler)(char *pPropName, DVector *pAngles); // pAngles = (pitch, yaw, roll)
+
+ // Fills in the GenericProp for the different data types. For a list
+ // of which property types map to which GenericProp variable, see
+ // the GenericProp structure.
+ // Note: if the property exists, it always initializes the members in the prop first,
+ // so if the GenericProp variable doesn't support that property type,
+ // it'll be zero (or ROT_INIT'd).
+ DRESULT (*GetPropGeneric)(char *pPropName, GenericProp *pProp);
+
+
+ // See if a property exists. If so, pPropType is filled in (if it's non-NULL) with
+ // on of the PT_ defines. Returns DE_NOTFOUND if it doesn't exist.
+ DRESULT (*DoesPropExist)(char *pPropName, int *pPropType);
+
+ // Get handles from objects and objects from handles. Note: HandleToObject will return
+ // NULL if the given object doesn't reside on this server (it's controlled remotely).
+ HOBJECT (*ObjectToHandle)(LPBASECLASS pObject);
+ LPBASECLASS (*HandleToObject)(HOBJECT hObject);
+
+ // Tests if a command is on for this client.
+ DBOOL (*IsCommandOn)(HCLIENT hClient, int command);
+
+ // OBSOLETE. Use CommonLT::GetRotationVectors.
+ virtual DRESULT GetRotationVectors(DRotation *pRotation,
+ DVector *pUp, DVector *pRight, DVector *pForward)=0;
+
+ // Gets orientation vectors, given an angle vector (x, y, and z rotations).
+ void (*GetRotationVectorsFromMatrix)(DMatrix *pMat,
+ DVector *pUp, DVector *pRight, DVector *pForward);
+
+ // Does a (fast) upper-case string comparison of the 2 strings.
+ DBOOL (*UpperStrcmp)(char *pStr1, char *pStr2);
+
+ // Rotate this rotation around the given axis by a certain amount.
+ void (*RotateAroundAxis)(DRotation *pRotation, DVector *pAxis, float amount);
+
+ // Treat the rotation like Euler angles...
+ void (*EulerRotateX)(DRotation *pRotation, float amount);
+ void (*EulerRotateY)(DRotation *pRotation, float amount);
+ void (*EulerRotateZ)(DRotation *pRotation, float amount);
+
+ // Align a rotation to a normal and spin it.
+ // Use pUp to set the frame of reference.
+ // If pUp is NULL or the same direction as pVector, then DirectEngine
+ // will kludge an up vector.
+ void (*AlignRotation)(DRotation *pRotation, DVector *pVector, DVector *pUp);
+
+ // OBSOLETE: use CommonLT::SetupEuler.
+ virtual DRESULT SetupEuler(DRotation *pRotation, float pitch, float yaw, float roll)=0;
+
+ // Interpolate between two rotations (with quaternions).
+ DRESULT (*InterpolateRotation)(DRotation *pDest, DRotation *pRot1, DRotation *pRot2, float t);
+
+ // Create a transformation matrix from a translation, rotation.
+ void (*SetupTransformationMatrix)( DMatrix *pMat, DVector *pTranslation, DRotation *pRotation );
+ // Create a translation matrix for the given translation.
+ void (*SetupTranslationMatrix)( DMatrix *pMat, DVector *pTranslation );
+ // Create a rotation matrix for the given rotation.
+ void (*SetupRotationMatrix)(DMatrix *pMat, DRotation *pRot);
+ // Create a translation vector from a tranformation matrix.
+ void (*SetupTranslationFromMatrix)( DVector *pTranslation, DMatrix *pMat );
+ // Create a rotation for the given tranformation matrix.
+ void (*SetupRotationFromMatrix)(DRotation *pRot, DMatrix *pMat);
+
+
+ // Rotate around a point.
+ void (*SetupRotationAroundPoint)(DMatrix *pMat, DRotation *pRot, DVector *pPoint);
+
+ // Parse a string for arguments. Works similar to command line parser.
+ // args within quotation marks are considered one arg.
+ // Returns the all args after pCommand and before end of string or semi-colon.
+ // pCommand - Beginning of string.
+ // pNewCommandPos - Parse fills this in with the ending position
+ // argBuffer - memory Parse can use as scratchpad
+ // argPointers - Parse fills these pointers in to point to args found.
+ // nArgs - Parse fills in the number of arguments found.
+ // Return - DTRUE, semicolon found, more args in string. DFALSE, no more args.
+ int (*Parse)(char *pCommand, char **pNewCommandPos, char *argBuffer, char **argPointers, int *nArgs);
+
+ // Sound functions.
+
+ // Play a sound with full control
+ // Arguments:
+ // pPlaySoundInfo - sound control structure
+ // Returns:
+ // DE_OK if successful.
+ // DE_ERROR on error.
+ DRESULT (*PlaySound)( PlaySoundInfo *pPlaySoundInfo );
+
+ // Get total length in seconds of sound.
+ // Arguments:
+ // hSound - Handle to sound.
+ // fDuration - Duration of sound.
+ // Returns:
+ // DE_OK if successful.
+ // DE_INVALIDPARAMS if hSound not available or not tracking time.
+ DRESULT (*GetSoundDuration)( HSOUNDDE hSound, DFLOAT *fDuration );
+
+ // IsSoundDone
+ // Arguments:
+ // hSound - Handle to sound.
+ // bDone - Indicates sound is completed.
+ // Returns:
+ // DE_OK if successful.
+ // DE_INVALIDPARAMS if hSound not available or not tracking time.
+ DRESULT (*IsSoundDone)( HSOUNDDE hSound, DBOOL *bDone );
+
+ // Kill a sound.
+ // Arguments:
+ // hSoundHandle - Handle to sound.
+ // Returns:
+ // DE_OK if successful.
+ // DE_ERROR on error.
+ DRESULT (*KillSound)( HSOUNDDE hSound );
+
+
+ // Inter-object link manipulation.
+
+ // If you want to hold on to an HOBJECT and get notification when the
+ // object is removed from the world, you can create an inter-object link
+ // between the two. The owner will get MID_LINKBROKEN notification when
+ // the link is being broken (by either the owner or linked object being removed).
+ // If a link between the two objects already exists, the function will not
+ // create another link and return DE_OK.
+ // An object cannot make a link to itself. This will return DE_ERROR.
+ DRESULT (*CreateInterObjectLink)(HOBJECT hOwner, HOBJECT hLinked);
+
+ // Breaks an inter-object link between the owner and linked object
+ // (if one exists..) You can only break a link from the owner, since
+ // the linked object doesn't even know it's linked to the owner..
+ // Note: MID_LINKBROKEN will NOT be called.
+ void (*BreakInterObjectLink)(HOBJECT hOwner, HOBJECT hLinked);
+
+
+ // Object manipulation.
+
+ // Attaches hChild to hParent. If pNodeName is set, it'll attach hChild to a
+ // specific node on hParent.
+ // DE will automatically detach if you remove hParent,
+ // but it will NOT automatically detach if you remove hChild. If you remove the
+ // child without removing the attachment, the results are undefined.
+ // Returns DE_OK, DE_NODENOTFOUND, or DE_INVALIDPARAMS.
+ DRESULT (*CreateAttachment)(HOBJECT hParent, HOBJECT hChild, char *pNodeName,
+ DVector *pOffset, DRotation *pRotationOffset, HATTACHMENT *pAttachment);
+
+ // Removes an attachment. Note: an attachment becomes invalid when you remove the parent
+ // so it'll crash if you call it with an attachment with a parent you've removed.
+ DRESULT (*RemoveAttachment)(HATTACHMENT hAttachment);
+
+ // Look for an attachment on the parent. Returns LT_ERROR, DE_NOTFOUND,
+ // or LT_OK if it found it. hAttachment is set to NULL if there's an error.
+ DRESULT (*FindAttachment)(HOBJECT hParent, HOBJECT hChild, HATTACHMENT *hAttachment);
+
+
+ // Get/Set object color info (RGBA 0-1).
+ // All objects default to (0,0,0,1)
+ // For lights, this changes the light's color.
+ // For models, this brightens a model's shading.
+ DBOOL (*GetObjectColor)(HOBJECT hObject, float *r, float *g, float *b, float *a);
+ DBOOL (*SetObjectColor)(HOBJECT hObject, float r, float g, float b, float a);
+
+ // Get/Set an object's user-defined flags.
+ DDWORD (*GetObjectUserFlags)(HOBJECT hObj);
+ DRESULT (*SetObjectUserFlags)(HOBJECT hObj, DDWORD flags);
+
+ // OBSOLETE: use the CommonLT ones.
+ virtual float GetObjectMass(HOBJECT hObj)=0;
+ virtual void SetObjectMass(HOBJECT hObj, float mass)=0;
+
+ // OBSOLETE: Use PhysicsLT.
+ virtual float GetForceIgnoreLimit(HOBJECT hObj, float &limit)=0;
+ virtual void SetForceIgnoreLimit(HOBJECT hObj, float limit)=0;
+
+ // Use this to iterate thru all the objects in the world.
+ // Pass in NULL to start off with. It'll return NULL when
+ // you have iterated through all the objects.
+ // This is generally a bad idea, but sometimes you have to.
+ HOBJECT (*GetNextObject)(HOBJECT hObj);
+
+ // Same as GetNextObject, but this iterates over all the inactive objects.
+ HOBJECT (*GetNextInactiveObject)(HOBJECT hObj);
+
+ // OBSOLETE: Use CommonLT version.
+ short GetObjectType(HOBJECT hObj) {DDWORD temp; Common()->GetObjectType(hObj, &temp); return (short)temp;}
+
+ // Get the object's name.
+ char* (*GetObjectName)(HOBJECT hObject);
+
+ // Set an object's friction coefficient.
+ virtual DRESULT SetFrictionCoefficient(HOBJECT hObj, float coeff)=0;
+
+ // This is a counter that controls when each object gets its Update()
+ // function called. This is set to 0.0001 when an object is created
+ // so by default, Update() gets called right away.
+ void (*SetNextUpdate)(HOBJECT hObj, DFLOAT nextUpdate);
+
+ // Sets the time which the engine will automatically deactivate an object. If object
+ // is currently autodeactivated, then this call will activate the object
+ void (*SetDeactivationTime)(HOBJECT hObj, DFLOAT fDeactivationTime);
+
+ // Activates any objects seen by this object
+ void (*PingObjects)(HOBJECT hObj);
+
+ // Object data accessors.
+ void (*GetObjectPos)(HOBJECT hObj, DVector *pos);
+ void (*SetObjectPos)(HOBJECT hObj, DVector *pos); // Exactly the same as calling Teleport().
+
+ // Scale the object (only works on models and sprites).
+ void (*ScaleObject)(HOBJECT hObj, DVector *pNewScale);
+ DRESULT (*GetObjectScale)(HOBJECT hObj, DVector *pScale);
+
+ // OBSOLETE. Use PhysicsLT::MoveObject.
+ virtual DRESULT MoveObject(HOBJECT hObj, DVector *pNewPos)=0;
+
+ // Teleports the object directly to the position.
+ DRESULT (*TeleportObject)(HOBJECT hObj, DVector *pNewPos);
+
+ // OBSOLETE. Use PhysicsLT::GetStandingOn.
+ virtual DRESULT GetStandingOn(HOBJECT hObj, CollisionInfo *pInfo)=0;
+
+ // Get information about the last collision. Only valid during MID_TOUCHNOTIFY or MID_CRUSH messages.
+ DRESULT (*GetLastCollision)(CollisionInfo *pInfo);
+
+ // Get/Set the object's rotation.
+ DRESULT (*GetObjectRotation)(HOBJECT hObj, DRotation *pRotation);
+ DRESULT (*SetObjectRotation)(HOBJECT hObj, DRotation *pRotation);
+
+ // This rotates the object to the new rotation with possible client side interpolation
+ DRESULT (*RotateObject)(HOBJECT hObj, DRotation *pRotation);
+
+ // Tilt their acceleration to be along the plane they're standing on.
+ void (*TiltToPlane)(HOBJECT hObj, DVector *pNormal);
+
+ // Get/Set the object's flags.
+ DDWORD (*GetObjectFlags)(HOBJECT hObj);
+ void (*SetObjectFlags)(HOBJECT hObj, DDWORD flags);
+
+ // Get/set an object's net flags. Net flags are a combination of NETFLAG_ defines.
+ virtual DRESULT GetNetFlags(HOBJECT hObj, DDWORD &flags)=0;
+ virtual DRESULT SetNetFlags(HOBJECT hObj, DDWORD flags)=0;
+
+ // Get/Set the object's state. State is one of the OBJSTATE_ defines above.
+ void (*SetObjectState)(HOBJECT hObj, int state);
+ int (*GetObjectState)(HOBJECT hObj);
+
+ // OBSOLETE. Use PhysicsLT.
+ virtual void GetObjectDims(HOBJECT hObj, DVector *pNewDims)=0;
+ virtual DRESULT SetObjectDims(HOBJECT hObj, DVector *pNewDims)=0;
+ virtual DRESULT SetObjectDims2(HOBJECT hObj, DVector *pNewDims)=0;
+
+ // OBSOLETE: use CommonLT functions.
+ virtual DRESULT GetVelocity(HOBJECT hObj, DVector *pVel)=0;
+ virtual DRESULT SetVelocity(HOBJECT hObj, DVector *pVel)=0;
+ virtual DRESULT GetAcceleration(HOBJECT hObj, DVector *pAccel)=0;
+ virtual DRESULT SetAcceleration(HOBJECT hObj, DVector *pAccel)=0;
+
+ // Get/Set blocking priority (defaults to 0).
+ // See FAQ for a description of how this works.
+ void (*SetBlockingPriority)(HOBJECT hObj, DBYTE pri);
+ DBYTE (*GetBlockingPriority)(HOBJECT hObj);
+
+
+ // Sprite manipulation.
+
+ // This clips the sprite on the poly.
+ // Returns DE_OK or DE_ERROR if not a sprite.
+ // Pass in INVALID_HPOLY to un-clip the sprite.
+ DRESULT (*ClipSprite)(HOBJECT hObj, HPOLY hPoly);
+
+
+ // Light manipulation.
+
+ // Get/Set a light's color (RGB, 0.0f to 1.0f).
+ // When you create a light, its color defaults to (0,0,0).
+
+ // Note: a light's color is snapped to 256 different values, so if
+ // you want to do any fancy interpolation or anything, you'll need
+ // to store your own, higher precision, color values.
+
+ // Note: this just calls GetObjectColor/SetObjectColor.
+ void (*GetLightColor)(HOBJECT hObj, float *r, float *g, float *b);
+ void (*SetLightColor)(HOBJECT hObj, float r, float g, float b);
+
+ // Get/Set a light's radius.
+ // When you create a light, its radius defaults to 100.
+ float (*GetLightRadius)(HOBJECT hObj);
+ void (*SetLightRadius)(HOBJECT hObj, float radius);
+
+
+ // Model manipulation.
+
+ // Iterate through the model's nodes. Returns DE_FINISHED when there are no more.
+ // hCurNode = INVALID_MODEL_NODE;
+ // while(interface->GetNextModelNode(hModel, hCurNode, &hCurNode) == DE_OK)
+ // { ... }
+ DRESULT (*GetNextModelNode)(HOBJECT hObject, HMODELNODE hNode, HMODELNODE *pNext);
+
+ // Get a model node's name.
+ DRESULT (*GetModelNodeName)(HOBJECT hObject, HMODELNODE hNode, char *pName, DDWORD maxLen);
+
+ // Get a model's command string.
+ DRESULT (*GetModelCommandString)(HOBJECT hObj, char *pStr, DDWORD maxLen);
+
+ // Hide/unhide a node on the model (they're all unhidden by default).
+ // Returns DE_OK, DE_ERROR, LT_NOCHANGE, or DE_NODENOTFOUND.
+ DRESULT (*SetModelNodeHideStatus)(HOBJECT hObj, char *pNodeName, DBOOL bHidden);
+ DRESULT (*GetModelNodeHideStatus)(HOBJECT hObj, char *pNodeName, /* out */DBOOL *bHidden);
+
+ // Get the current (global) transformation for a model node.
+ // Returns DFALSE if the node does not exist or if the object
+ // you pass in is not a model.
+ DBOOL (*GetModelNodeTransform)(HOBJECT hObj, char *pNodeName,
+ DVector *pPos, DRotation *pRot);
+
+ // Get the absolute world position and rotation of a node on an attached model.
+ // Inputs:
+ // hAttachment - Attachment created with CreateAttachment
+ // pChildNodeName - name of node on attached child model
+ // Outputs:
+ // pPos - absolute world position of node.
+ // pRot - absolute world rotation of node.
+ DRESULT (*GetAttachedModelNodeTransform)( HATTACHMENT hAttachment, char *pChildNodeName, DVector *pPos, DRotation *pRot);
+
+
+ // Get an animation index from a model.
+ // Returns -1 if the animation doesn't exist (or if the object isn't a model).
+ HMODELANIM (*GetAnimIndex)(HOBJECT hObj, char *pAnimName);
+
+ // If the object is a model, this sets its current animation.
+ void (*SetModelAnimation)(HOBJECT hObj, HMODELANIM hAnim);
+
+ // Returns the animation the model is currently on. (HMODELANIM)-1 if none.
+ HMODELANIM (*GetModelAnimation)(HOBJECT hObj);
+
+ // Starts the current animation over.
+ DRESULT (*ResetModelAnimation)(HOBJECT hObj);
+
+ // Tells what the playback state of the model is (a combination of the
+ // MS_ bits defined in basedefs_de.h).
+ DDWORD (*GetModelPlaybackState)(HOBJECT hObj);
+
+ // Get/Set the looping state of the model. The default state is TRUE.
+ void (*SetModelLooping)(HOBJECT hObj, DBOOL bLoop);
+ DBOOL (*GetModelLooping)(HOBJECT hObj);
+
+ // Get the model filenames. You can pass in DNULL for pFilename and pSkinName.
+ // Returns DFALSE if the object is not a model.
+ // Initializes pFilename or pSkinName to zero length if the model doesn't have
+ // a filename or skin.
+ DBOOL (*GetModelFilenames)(HOBJECT hObj, char *pFilename, int fileBufLen, char *pSkinName, int skinBufLen);
+
+ // Change the object filenames (works on models and sprites.. SetModelFilenames
+ // is the same as SetObjectFilenames). Even if it fails on the server and
+ // returns an error, it'll still send a message to the clients.
+ DRESULT (*SetModelFilenames)(HOBJECT hObj, char *pFilename, char *pSkinName);
+ DRESULT (*SetObjectFilenames)(HOBJECT hObj, char *pFilename, char *pSkinName);
+
+ // Get the endpoints of the model's extents for its current animation frame.
+ // This is in world space so if you just want the dimensions, take (pMax - pMin) / 2.
+ // Returns DE_ERROR if it's not a model.
+ DRESULT (*GetModelFrameBox)(HOBJECT hObj, DVector *pMin, DVector *pMax);
+
+ // OBSOLETE: use CommonLT.
+ virtual DRESULT GetModelAnimUserDims(HOBJECT hObj, DVector *pDims, HMODELANIM hAnim)=0;
+
+
+ // Container manipulation.
+
+ // Get the container's container code (can only be set in the ObjectCreateStruct during creation).
+ // Returns DFALSE if the object isn't a container.
+ DBOOL (*GetContainerCode)(HOBJECT hObj, D_WORD *pCode);
+
+ // Gets the list of containers the object is inside.
+ // pFlagList must be the same size as pContainerList.
+ // Returns the number of elements in pList filled in.
+ DDWORD (*GetObjectContainers)(HOBJECT hObj,
+ HOBJECT *pContainerList, DDWORD *pFlagList, DDWORD maxListSize);
+
+ // Gets the list of objects inside the container.
+ // Returns the number of elements in pList filled in.
+ DDWORD (*GetContainedObjects)(HOBJECT hContainer,
+ HOBJECT *pObjectList, DDWORD *pFlagList, DDWORD maxListSize);
+
+ DDWORD (*GetPointContainers)(DVector *pPoint, HOBJECT *pList, DDWORD maxListSize);
+
+
+ // Surface manipulation.
+
+ // OBSOLETE: use CommonLT.
+ virtual DRESULT GetPolyTextureFlags(HPOLY hPoly, DDWORD *pFlags)=0;
+
+
+ // Save game
+
+ // dwParam gets passed into MID_SAVEOBJECT as fData.
+ // Flags is a SAVEOBJECTS_ define.
+ DRESULT (*SaveObjects)(char *pszSaveFileName, ObjectList *pList, DDWORD dwParam, DDWORD flags);
+
+ // dwParam gets passed into MID_LOADOBJECT as fData.
+ // Flags is a combination of RESTOREOBJECTS_ defines.
+ DRESULT (*RestoreObjects)( char *pszRestoreFileName, DDWORD dwParam, DDWORD flags );
+
+
+ // Load world
+
+ // Flags is a combination of the LOADWORLD_ flags.
+ DRESULT (*LoadWorld)(char *pszWorldFileName, DDWORD flags);
+ DRESULT (*RunWorld)();
+
+
+ // Network session manipulation
+
+ // Updates the sessions' name.
+ DRESULT (*UpdateSessionName)(const char* sName);
+
+ // Gets the sessions' name.
+ DRESULT (*GetSessionName)(char* sName, DDWORD dwBufferSize);
+
+ // Send a message to the standalone server app. Returns LT_NOTFOUND
+ // if there is no server app or if it isn't setup to receive the message.
+ DRESULT (*SendToServerApp)(char *pMsg);
+
+ // Gets the tcp/ip address of the main driver if available.
+ // If you're hosting a game, hostPort is filled in with the port you're hosting on.
+ // If not, it's set to 0xFFFF.
+ DRESULT (*GetTcpIpAddress)(char* sAddress, DDWORD dwBufferSize, D_WORD &hostPort);
+
+ // Get a list of files/directories in a directory (pass in "" to start with).
+ // The list is a noncircular linked list with DNULL terminating it.
+ FileEntry* (*GetFileList)(char *pDirName);
+
+ // Use FreeFileList when you're done with each list you get.
+ void (*FreeFileList)(FileEntry *pHead);
+
+
+ protected:
+
+ CommonLT *m_pCommonLT;
+ PhysicsLT *m_pPhysicsLT;
+ };
+
+
+ // For backward compatibility.. never use this.
+ #define CServerDE ServerDE
+
+
+#endif // __SERVER_DE_H__
+
+
+
diff --git a/AppHeaders/serverobj_de.h b/AppHeaders/serverobj_de.h
new file mode 100644
index 0000000..a8ab5d6
--- /dev/null
+++ b/AppHeaders/serverobj_de.h
@@ -0,0 +1,539 @@
+
+// serverobj_de defines all the necessary things for writing an object.
+
+#ifndef __SERVEROBJ_DE_H__
+#define __SERVEROBJ_DE_H__
+
+
+ #include "basedefs_de.h"
+ #include "servershell_de.h"
+
+
+
+ // Used for containers to apply physics to an object.
+ // You can change velocity, acceleration, and flags without changing the object's
+ // actual values.
+ typedef struct ContainerPhysics_t
+ {
+ DVector m_Acceleration;
+ DVector m_Velocity;
+ DDWORD m_Flags;
+ HOBJECT m_hObject;
+ } ContainerPhysics;
+
+
+ // Different property types.
+ #define PT_STRING 0
+ #define PT_VECTOR 1
+ #define PT_COLOR 2
+ #define PT_REAL 3
+ #define PT_FLAGS 4
+ #define PT_BOOL 5
+ #define PT_LONGINT 6
+ #define PT_ROTATION 7
+ #define NUM_PROPERTYTYPES 8
+
+ // Property flags.
+ #define PF_HIDDEN (1<<0) // Property doesn't show up in DEdit.
+ #define PF_RADIUS (1<<1) // Property is a number to use as radius for drawing circle. There can be more than one.
+ #define PF_DIMS (1<<2) // Property is a vector to use as dimensions for drawing box. There can be only one.
+ #define PF_FIELDOFVIEW (1<<3) // Property is a field of view.
+ #define PF_LOCALDIMS (1<<4) // Used with PF_DIMS. Causes DEdit to show dimensions rotated with the object.
+ #define PF_GROUPOWNER (1<<5) // This property owns the group it's in.
+ #define PF_GROUP1 (1<<6) // This property is in group 1.
+ #define PF_GROUP2 (1<<7) // This property is in group 2.
+ #define PF_GROUP3 (1<<8) // This property is in group 3.
+ #define PF_GROUP4 (1<<9) // This property is in group 4.
+ #define PF_GROUP5 (1<<10) // This property is in group 5.
+ #define PF_GROUP6 (1<<11) // This property is in group 6.
+
+ // Used internally..
+ #define PF_GROUPMASK (PF_GROUP1|PF_GROUP2|PF_GROUP3|PF_GROUP4|PF_GROUP5|PF_GROUP6)
+
+ // Class flags.
+ #define CF_HIDDEN (1<<0) // Instances of the class can't be created in DEdit.
+ #define CF_NORUNTIME (1<<1) // This class doesn't get used at runtime (the engine
+ // won't instantiate these objects out of the world file).
+ #define CF_STATIC (1<<2) // This is a special class that the server creates an
+ // instance of at the same time that it creates the
+ // server shell. The object is always around. This
+ // should be used as much as possible instead of adding
+ // code to the server shell.
+ #define CF_ALWAYSLOAD (1<<3) // Objects of this class and sub-classes are always loaded from the level
+ // file and can't be saved to a save game.
+
+
+
+ #define PRECREATE_NORMAL 0.0f // Object is being created at runtime.
+ #define PRECREATE_WORLDFILE 1.0f // Object is being loaded from a world file. Read props in.
+ #define PRECREATE_STRINGPROP 2.0f // Object is created from CreateObjectProps. Use GetPropGeneric to read props.
+ #define PRECREATE_SAVEGAME 3.0f // Object comes from a savegame.
+
+ #define INITIALUPDATE_NORMAL 0.0f // Normal creation.
+ #define INITIALUPDATE_WORLDFILE 1.0f // Being created from a world file.
+ #define INITIALUPDATE_STRINGPROP 2.0f // Object is created from CreateObjectProps. Use GetPropGeneric to read props.
+ #define INITIALUPDATE_SAVEGAME 3.0f // Created from a savegame.
+
+
+ // Here are all the message IDs and structures that LithTech uses.
+
+ // This is called right before the server uses the ObjectCreateStruct
+ // to create its internal structure for the object.
+ // pData = ObjectCreateStruct*
+ // fData = a PRECREATE_ define above.
+ #define MID_PRECREATE 0
+
+ // This is called right after your object is created (kind of like the opposite
+ // of MID_POSTPROPREAD).
+ // fData is an INITIALUPDATE_ define above.
+ #define MID_INITIALUPDATE 1
+
+ // This is called when NextUpdate goes to zero.
+ #define MID_UPDATE 2
+
+ // This is called when you touch another object.
+ // pData is an HOBJECT for the other object.
+ // fData is the collision (stopping) force (based on masses and velocities).
+ #define MID_TOUCHNOTIFY 3
+
+ // This is notification when a link to an object is about to be broken.
+ // pData is an HOBJECT to the link's object.
+ #define MID_LINKBROKEN 4
+
+ // This is notification when a model string key is crossed.
+ // (You only get it if your FLAG_MODELKEYS flag is set).
+ // pData is an ArgList*.
+ #define MID_MODELSTRINGKEY 5
+
+ // Called when an object pushes you into a wall. It won't
+ // move any further unless you make yourself nonsolid (ie: a player would
+ // take damage from each crush notification, then die).
+ // pData is the HOBJECT of the object crushing you.
+ #define MID_CRUSH 6
+
+ // Load and save yourself for a serialization.
+ // pData is an HMESSAGEREAD or HMESSAGEWRITE.
+ // fData is the dwParam passed to ServerDE::SaveObjects or ServerDE::RestoreObjects.
+ #define MID_LOADOBJECT 7
+ #define MID_SAVEOBJECT 8
+
+ // Called for a container for objects inside it each frame. This gives you a chance
+ // to modify the physics applied to an object WITHOUT actually modifying its
+ // velocity or acceleration (great way to dampen velocity..)
+ // pData is a ContainerPhysics*.
+ #define MID_AFFECTPHYSICS 9
+
+ // The parent of an attachment between you and it is being removed.
+ #define MID_PARENTATTACHMENTREMOVED 10
+
+ // Called every frame on client objects. This gives you a chance to force
+ // updates on certain objects so they never get removed for the client.
+ // pData is a ForceUpdate*.
+ // (LT automatically adds the client object and the sky objects to this list to start with).
+ #define MID_GETFORCEUPDATEOBJECTS 11
+
+
+
+
+
+ // These are your (optional) construct/destruct functions.
+ // In C++, you should ALWAYS use the default ones, because they
+ // will call your constructor/destructor. In C, you can use
+ // them to init and term your object. In most cases, you should
+ // add any aggregates you have in your construct function, since
+ // ReadProp/PostPropRead get called right after and your aggregates
+ // might want to look at them.
+ typedef void (*ConstructObjectFn)(void *pObject);
+ typedef void (*DestructObjectFn)(void *pObject);
+
+
+ // Your object should implement this and call its base class's
+ // message function at the end.
+ typedef DDWORD (*EngineMessageFn)(LPBASECLASS pObject, DDWORD messageID, void *pData, float fData);
+
+ // This is called when an object sends a message to you.
+ // You should call your base class's object message function after you handle this.
+ typedef DDWORD (*ObjectMessageFn)(LPBASECLASS pObject, HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead);
+
+
+ typedef struct PropDef_t
+ {
+
+ PropDef_t(char *pName, short type, DVector valVec,
+ float valFloat, char *valString, short propFlags)
+ {
+ m_PropName = pName;
+ m_PropType = type;
+ m_DefaultValueVector = valVec;
+ m_DefaultValueFloat = valFloat;
+ m_DefaultValueString = valString;
+ m_PropFlags = propFlags;
+ m_pInternal = 0;
+ }
+
+ char *m_PropName;
+
+ // One of the PT_ defines above.
+ short m_PropType;
+
+ // Default vector/color value.
+ DVector m_DefaultValueVector;
+
+ float m_DefaultValueFloat;
+ char *m_DefaultValueString;
+
+ short m_PropFlags;
+
+ // Don't touch!
+ void *m_pInternal;
+
+ } PropDef;
+
+
+ typedef struct ClassDef_t
+ {
+
+ char *m_ClassName;
+
+ struct ClassDef_t *m_ParentClass;
+
+ // A combination of the CF_ flags above.
+ DDWORD m_ClassFlags;
+
+ ConstructObjectFn m_ConstructFn;
+ DestructObjectFn m_DestructFn;
+ EngineMessageFn m_EngineMessageFn;
+ ObjectMessageFn m_ObjectMessageFn;
+
+ short m_nProps;
+ PropDef *m_Props;
+
+ // How big an object of this class is (set automatically).
+ long m_ClassObjectSize;
+
+ // Don't touch!
+ void *m_pInternal[2];
+
+ } ClassDef;
+
+
+ #include "server_de.h"
+ #include "aggregate_de.h"
+
+
+ // This is always available, once you create your server shell.
+ class ServerDE;
+ extern ServerDE *g_pServerDE;
+
+
+ // Used to avoid crashes from version mismatches.
+ #define SERVEROBJ_VERSION 1
+
+
+
+
+ // You MUST have one source file that lists out all the classes you have defined
+ // using these macros.
+ #ifdef COMPILE_WITH_C
+ #define BEGIN_CLASSDEFS1()
+ #else
+ #define BEGIN_CLASSDEFS1() __ClassDefiner *__g_ClassDefinerHead=0;
+ #endif
+
+ #define DEFINECLASS1(name) extern ClassDef _##name##_Class__;
+ #define END_CLASSDEFS1()
+
+ #define BEGIN_CLASSDEFS2() \
+ static ClassDef *__GlobalClassDefList__[] = { \
+
+ #define DEFINECLASS2(name) \
+ &_##name##_Class__,
+
+ #define END_CLASSDEFS2() \
+ }; \
+ static int __GlobalClassDefListSize__ = sizeof(__GlobalClassDefList__) / sizeof(__GlobalClassDefList__[0]); \
+ ServerDE *g_pServerDE=(ServerDE*)0;\
+ BEGIN_EXTERNC() \
+ __declspec(dllexport) ClassDef** ObjectDLLSetup(int *nDefs, ServerDE *pServer, int *version); \
+ END_EXTERNC() \
+ ClassDef** ObjectDLLSetup(int *nDefs, ServerDE *pServer, int *version) \
+ {\
+ *version = SERVEROBJ_VERSION;\
+ g_pServerDE = pServer;\
+ *nDefs = __GlobalClassDefListSize__; \
+ return __GlobalClassDefList__; \
+ }
+
+
+ // In C++, you can use this macro instead of the BEGIN_CLASSDEFS macros
+ // so you don't have to add each object to the list.
+ #ifndef COMPILE_WITH_C
+ class __ClassDefiner;
+ extern __ClassDefiner *__g_ClassDefinerHead;
+
+ class __ClassDefiner
+ {
+ public:
+
+ __ClassDefiner(ClassDef *pDef)
+ {
+ m_pClass = pDef;
+ m_pNext = __g_ClassDefinerHead;
+ __g_ClassDefinerHead = this;
+ }
+
+ ClassDef *m_pClass;
+ __ClassDefiner *m_pNext;
+
+ };
+
+ extern ClassDef **__g_cpp_classlist;
+ class __cpp_classlist_auto_free {
+ public:
+ ~__cpp_classlist_auto_free() {
+ if(__g_cpp_classlist) {
+ free(__g_cpp_classlist);
+ __g_cpp_classlist = 0;
+ }
+ }
+ };
+
+ #define DEFINE_CLASSES() \
+ ClassDef **__g_cpp_classlist=0;\
+ __cpp_classlist_auto_free __free_the_g_cpp_classlist;\
+ ServerDE *g_pServerDE=(ServerDE*)0;\
+ BEGIN_EXTERNC() \
+ __declspec(dllexport) ClassDef** ObjectDLLSetup(int *nDefs, ServerDE *pServer, int *version); \
+ END_EXTERNC() \
+ __ClassDefiner *__g_ClassDefinerHead=0;\
+ ClassDef** ObjectDLLSetup(int *nDefs, ServerDE *pServer, int *version) \
+ {\
+ int nClasses;\
+ __ClassDefiner *pCurDefiner;\
+ *version = SERVEROBJ_VERSION;\
+ g_pServerDE = pServer;\
+ nClasses=0;\
+ pCurDefiner = __g_ClassDefinerHead;\
+ while(pCurDefiner)\
+ {\
+ pCurDefiner = pCurDefiner->m_pNext;\
+ ++nClasses;\
+ }\
+ __g_cpp_classlist = (ClassDef**)malloc(sizeof(ClassDef*) * nClasses);\
+ nClasses=0;\
+ pCurDefiner = __g_ClassDefinerHead;\
+ while(pCurDefiner)\
+ {\
+ __g_cpp_classlist[nClasses] = pCurDefiner->m_pClass;\
+ pCurDefiner = pCurDefiner->m_pNext;\
+ ++nClasses;\
+ }\
+ *nDefs = nClasses; \
+ return __g_cpp_classlist; \
+ }
+
+ #endif
+
+
+
+
+ // -------------------------------------------------------- //
+ // These are the macros that you use to define classes.
+ // -------------------------------------------------------- //
+
+ #ifdef __cplusplus
+ #define ALLOCATEONE(type) (void*)(new type)
+ #define DELETEONE(type, ptr) delete ((type*)ptr)
+ #else
+ #define ALLOCATEONE(type) malloc(sizeof(type))
+ #define DELETEONE(type, ptr) free(ptr)
+ #endif
+
+
+ #ifndef COMPILE_WITH_C
+ inline void* operator new(size_t size, void *ptr, int asdf, char a)
+ {
+ return ptr;
+ }
+
+ #if _MSC_VER != 1100
+ inline void operator delete(void *pDataPtr, void *ptr, int asdf, char a)
+ {
+ }
+ #endif
+ #endif
+
+
+ // It adds a dummy property here so C syntax doesn't break when you have no properties..
+ #define NOCOLOR DVector(0.0f, 0.0f, 0.0f)
+
+
+ // If you want level designers to be able to set object flags, you should
+ // use these macros so the property names are standardized.
+
+ // Use the ADD_X_FLAG macros in your property list.
+
+ #define ADD_VISIBLE_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Visible, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_SHADOW_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Shadow, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_ROTATEABLESPRITE_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(RotateableSprite, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_CHROMAKEY_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Chromakey, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_SOLID_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Solid, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_GRAVITY_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Gravity, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_TOUCHNOTIFY_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Touch Notify, PT_BOOL, defVal, 0, flags)
+
+ #define ADD_RAYHIT_FLAG(defVal, flags) \
+ ADD_PROP_FLAG(Rayhit, PT_BOOL, defVal, 0, flags)
+
+
+ // Full property definitions.
+ #define ADD_PROP_FLAG(name, type, valFloat, valString, flags) \
+ PropDef_t(#name, type, NOCOLOR, valFloat, valString, flags),
+
+ #define ADD_REALPROP_FLAG(name, val, flags) \
+ PropDef_t(#name, PT_REAL, NOCOLOR, val, "", flags),
+
+ #define ADD_STRINGPROP_FLAG(name, val, flags) \
+ PropDef_t(#name, PT_STRING, NOCOLOR, 0.0f, val, flags),
+
+ #define ADD_VECTORPROP_FLAG(name, flags) \
+ PropDef_t(#name, PT_VECTOR, NOCOLOR, 0.0f, (char*)0, flags),
+
+ #define ADD_VECTORPROP_VAL_FLAG(name, defX, defY, defZ, flags) \
+ PropDef_t(#name, PT_VECTOR, DVector(defX, defY, defZ), 0.0f, (char*)0, flags),
+
+ #define ADD_LONGINTPROP_FLAG(name, val, flags) \
+ PropDef_t(#name, PT_LONGINT, NOCOLOR, (float)val, (char*)0, flags),
+
+ #define ADD_ROTATIONPROP_FLAG(name, flags) \
+ PropDef_t(#name, PT_ROTATION, NOCOLOR, 0.0f, (char*)0, flags),
+
+ #define ADD_BOOLPROP_FLAG(name, val, flags) \
+ PropDef_t(#name, PT_BOOL, NOCOLOR, (float)val, (char*)0, flags),
+
+ #define ADD_COLORPROP_FLAG(name, valR, valG, valB, flags) \
+ PropDef_t(#name, PT_COLOR, DVector(valR, valG, valB), 0.0f, (char*)0, flags),
+
+
+
+ // Add properties without flags (only here for backward compatibility).
+ #define ADD_PROP(name, type, valFloat, valString) \
+ ADD_PROP_FLAG(name, type, valFloat, valString, 0)
+
+ #define ADD_REALPROP(name, val) \
+ ADD_REALPROP_FLAG(name, val, 0)
+
+ #define ADD_STRINGPROP(name, val) \
+ ADD_STRINGPROP_FLAG(name, val, 0)
+
+ #define ADD_VECTORPROP(name) \
+ ADD_VECTORPROP_FLAG(name, 0)
+
+ #define ADD_VECTORPROP_VAL(name, defX, defY, defZ) \
+ ADD_VECTORPROP_VAL_FLAG(name, defX, defY, defZ, 0)
+
+ #define ADD_LONGINTPROP(name, val) \
+ ADD_LONGINTPROP_FLAG(name, val, 0)
+
+ #define ADD_ROTATIONPROP(name) \
+ ADD_ROTATIONPROP_FLAG(name, 0)
+
+ #define ADD_BOOLPROP(name, val) \
+ ADD_BOOLPROP_FLAG(name, val, 0)
+
+ #define ADD_COLORPROP(name, valR, valG, valB) \
+ ADD_COLORPROP_FLAG(name, valR, valG, valB, 0)
+
+
+ // Define a group with this.
+ #define PROP_DEFINEGROUP(groupName, groupFlag) \
+ PropDef_t(#groupName, PT_LONGINT, NOCOLOR, (float)0.0f, (char*)0, groupFlag|PF_GROUPOWNER),
+
+
+ #define BEGIN_CLASS(name) \
+ static PropDef _##name##_Props__[] = { \
+ ADD_STRINGPROP("__NOPROP__!!", "")
+
+
+ // Define the default constructor/destructor functions.
+ #ifdef COMPILE_WITH_C
+ #define DO_AUTO_CLASSLIST(name)
+
+ #define DO_DEFAULT_FUNCTIONS(_className) \
+ void Default##_className##Constructor(void *ptr) {}\
+ void Default##_className##Destructor(void *ptr) {}
+ #else
+ #define DO_AUTO_CLASSLIST(name) \
+ static __ClassDefiner __##name##_definer(&_##name##_Class__);
+
+ #define DO_DEFAULT_FUNCTIONS(_className)\
+ void Default##_className##Constructor(void *ptr)\
+ {\
+ ::new(ptr, (int)0, (char)0) _className;\
+ }\
+ void Default##_className##Destructor(void *ptr)\
+ {\
+ _className *thePtr = (_className*)ptr;\
+ thePtr->~_className();\
+ }
+ #endif
+
+ #define END_CLASS_SYMBOL(name, parentSymbol, flags, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn, classFlags) \
+ ClassDef _##name##_Class__ = { \
+ #name, parentSymbol, \
+ flags,\
+ construct_fn, destruct_fn, \
+ (EngineMessageFn)enginemessage_fn,\
+ (ObjectMessageFn)objectmessage_fn,\
+ (sizeof(_##name##_Props__) / sizeof(PropDef)) - 1,\
+ &_##name##_Props__[1], \
+ sizeof(name),\
+ (void*)0, (void*)0 }; \
+ DO_AUTO_CLASSLIST(name)
+
+ // End class macros with flags.
+ #define END_CLASS_FLAGS(name, parent, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn, flags) \
+ }; \
+ extern ClassDef _##parent##_Class__; \
+ END_CLASS_SYMBOL(name, &_##parent##_Class__, flags, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn, 0)
+
+ #define END_CLASS_DEFAULT_FLAGS(name, parent, enginemessage_fn, objectmessage_fn, flags)\
+ }; \
+ extern ClassDef _##parent##_Class__; \
+ DO_DEFAULT_FUNCTIONS(name)\
+ END_CLASS_SYMBOL(name, &_##parent##_Class__, flags, Default##name##Constructor, Default##name##Destructor, enginemessage_fn, objectmessage_fn, 0)
+
+ // Normal end class macros.
+ #define END_CLASS(name, parent, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn) \
+ END_CLASS_FLAGS(name, parent, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn, 0)
+
+ #define END_CLASS_DEFAULT(name, parent, enginemessage_fn, objectmessage_fn)\
+ END_CLASS_DEFAULT_FLAGS(name, parent, enginemessage_fn, objectmessage_fn, 0)
+
+
+ // Only used internally.
+ #define END_CLASS_NOPARENT(name, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn) \
+ }; \
+ END_CLASS_SYMBOL(name, (ClassDef*)0, 0, construct_fn, destruct_fn, enginemessage_fn, objectmessage_fn, 0)
+
+ #define END_CLASS_DEFAULT_NOPARENT(name, enginemessage_fn, objectmessage_fn) \
+ }; \
+ DO_DEFAULT_FUNCTIONS(name)\
+ END_CLASS_SYMBOL(name, (ClassDef*)0, 0, Default##name##Constructor, Default##name##Destructor, enginemessage_fn, objectmessage_fn, 0)
+
+
+#endif // __SERVEROBJ_DE_H__
+
+
diff --git a/AppHeaders/servershell_de.h b/AppHeaders/servershell_de.h
new file mode 100644
index 0000000..efa2f79
--- /dev/null
+++ b/AppHeaders/servershell_de.h
@@ -0,0 +1,112 @@
+
+#ifndef __SERVERSHELL_DE_H__
+#define __SERVERSHELL_DE_H__
+
+
+ #include "basedefs_de.h"
+ #include "engineobjects_de.h"
+ #include "server_de.h"
+
+
+
+ /////////////////////////////////////////////////////////////////////
+ // ServerShellDE interface. You must implement this for a server.
+ /////////////////////////////////////////////////////////////////////
+
+ typedef struct ServerShellDE_t
+ {
+
+ // This is so DirectEngine will skip over a C++ object's VTable.
+ #ifdef COMPILE_WITH_C
+ void *cpp_4BytesForVTable;
+ #endif
+
+
+ // A message from the server app.
+ DRESULT (*ServerAppMessageFn)(struct ServerShellDE_t *pShell, char *pMsg);
+
+ // Notification when new clients log into the server.
+ void (*OnAddClient)(struct ServerShellDE_t *pShell, HCLIENT hClient);
+ void (*OnRemoveClient)(struct ServerShellDE_t *pShell, HCLIENT hClient);
+
+ // You must create an object to represent the client.
+ // It uses the object's position to determine what the client can see.
+ // The client data comes from the StartGameRequest from the client connecting.
+ LPBASECLASS (*OnClientEnterWorld)(struct ServerShellDE_t *pShell, HCLIENT hClient, void *pClientData, DDWORD clientDataLen);
+ void (*OnClientExitWorld)(struct ServerShellDE_t *pShell, HCLIENT hClient);
+
+ // Called before and after you switch worlds.
+ void (*PreStartWorld)(struct ServerShellDE_t *pShell, DBOOL bSwitchingWorlds);
+ void (*PostStartWorld)(struct ServerShellDE_t *pShell);
+
+ // Message handler.
+ void (*OnMessage)(struct ServerShellDE_t *pShell, HCLIENT hSender, DBYTE messageID, HMESSAGEREAD hMessage);
+
+ // Handler for messages from objects.
+ void (*OnObjectMessage)(struct ServerShellDE_t *pShell, LPBASECLASS pSender, DDWORD messageID, HMESSAGEREAD hMessage);
+
+ // Command notification.
+ void (*OnCommandOn)(struct ServerShellDE_t *pShell, HCLIENT hClient, int command);
+ void (*OnCommandOff)(struct ServerShellDE_t *pShell, HCLIENT hClient, int command);
+
+ // Update loop callback.. do whatever you like in here.
+ // Time since the last Update() call is passed in.
+ void (*Update)(struct ServerShellDE_t *pShell, DFLOAT timeElapsed);
+
+ // Called when a demo playback is done.
+ void (*OnPlaybackFinish)(struct ServerShellDE_t *pShell);
+
+ // This is where the main caching takes place. Call ServerDE::CacheFile() for
+ // each sprite, model, texture, and sound that you want to make sure are in
+ // memory for the level. The engine will get everything the level requires
+ // (any models or sprites that are in the level after it is loaded), but will
+ // unload everything else.
+ void (*CacheFiles)(struct ServerShellDE_t *pShell);
+
+ // You need to call SRand() here with a constant (done automatically in C++).
+ void (*SRand)(struct ServerShellDE_t *pShell);
+ } ServerShellDE;
+
+
+ class ServerDE;
+
+
+ #define SERVERSHELL_VERSION 3
+
+ typedef ServerShellDE* (*CreateServerShellFn)(ServerDE *pServerDE);
+ typedef void (*DeleteServerShellFn)(ServerShellDE *);
+
+ // You must implement these two functions to create and delete your server shell.
+ ServerShellDE* CreateServerShell(ServerDE *pServerDE);
+ void DeleteServerShell(ServerShellDE *);
+
+ // The HINSTANCE for the DLL.
+ extern void *g_hLTDLLInstance;
+
+
+ #define SETUP_SERVERSHELL()\
+ void *g_hLTDLLInstance=0;\
+ BEGIN_EXTERNC() \
+ __declspec(dllexport) void GetServerShellFunctions(CreateServerShellFn *pCreate, DeleteServerShellFn *pDelete);\
+ __declspec(dllexport) int GetServerShellVersion();\
+ __declspec(dllexport) void SetInstanceHandle(void *handle);\
+ END_EXTERNC()\
+ void GetServerShellFunctions(CreateServerShellFn *pCreate, DeleteServerShellFn *pDelete)\
+ {\
+ *pCreate = CreateServerShell;\
+ *pDelete = DeleteServerShell;\
+ }\
+ int GetServerShellVersion()\
+ {\
+ return SERVERSHELL_VERSION;\
+ }\
+ void SetInstanceHandle(void *handle)\
+ {\
+ g_hLTDLLInstance = handle;\
+ }
+
+
+#endif // __SERVERSHELL_DE_H__
+
+
+
diff --git a/AppHeaders/specialeffect_de.h b/AppHeaders/specialeffect_de.h
new file mode 100644
index 0000000..6bbaa05
--- /dev/null
+++ b/AppHeaders/specialeffect_de.h
@@ -0,0 +1,11 @@
+
+
+#ifndef __SPECIALEFFECT_DE_H__
+#define __SPECIALEFFECT_DE_H__
+
+
+
+
+
+#endif // __SPECIALEFFECT_DE_H__
+
diff --git a/Blood2Serv/CoolServ.cpp b/Blood2Serv/CoolServ.cpp
new file mode 100644
index 0000000..97603eb
--- /dev/null
+++ b/Blood2Serv/CoolServ.cpp
@@ -0,0 +1,324 @@
+// CoolServ.cpp : Defines the class behaviors for the application.
+//
+
+
+// Includes...
+
+#include "stdafx.h"
+#include "CoolServ.h"
+#include "GameServDlg.h"
+#include "NetStart.h"
+#include "ServerUtils.h"
+#include "RezFind.h"
+#include "Resource.h"
+
+
+// Macros...
+
+#define IsKeyDown(key) (GetAsyncKeyState(key) & 0x80000000)
+
+
+// Debug...
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+// Globals...
+
+ServerInfo g_ServerInfo;
+ServerOptions g_ServerOptions;
+NetGame g_NetGame;
+HINSTANCE g_hInst = NULL;
+BOOL g_bEmptyExit = FALSE;
+
+
+// Functions...
+
+/////////////////////////////////////////////////////////////////////////////
+// CCoolServApp
+
+BEGIN_MESSAGE_MAP(CCoolServApp, CWinApp)
+ //{{AFX_MSG_MAP(CCoolServApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCoolServApp construction
+
+CCoolServApp::CCoolServApp(LPCTSTR lpszAppName) : CWinApp(lpszAppName)
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CCoolServApp object
+
+CCoolServApp theApp("GameServ");
+
+CCoolServApp* GetTheApp()
+{
+ return(&theApp);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CCoolServApp initialization
+
+BOOL CCoolServApp::InitInstance()
+{
+ AfxEnableControlContainer();
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+
+ // Get our instance handle...
+
+ g_hInst = AfxGetInstanceHandle();
+
+ char *pDLLName = "server.dll";
+ int i;
+ for(i=0; i < (__argc-1); i++)
+ {
+ if(stricmp(__argv[i], "-DLL") == 0)
+ {
+ pDLLName = __argv[i+1];
+ break;
+ }
+ }
+
+ // Load the server dll...
+
+ if (!LoadServerDLL(pDLLName))
+ {
+ AfxMessageBox(IDS_ERROR_LOADSERVER);
+ return(FALSE);
+ }
+
+
+ // Get our server interface...
+
+ ServerInterface* pServerMgr = GetServerInterface();
+ if (!pServerMgr)
+ {
+ AfxMessageBox(IDS_ERROR_ACCESSSERVER);
+ return(FALSE);
+ }
+
+
+ // Check command-line paramters...
+
+ BOOL bNoDlgs = FALSE;
+
+ char sCmdLine[256];
+ strcpy(sCmdLine, theApp.m_lpCmdLine);
+ strupr(sCmdLine);
+
+ if (strlen(sCmdLine) > 0 && strstr(sCmdLine, "-GO"))
+ {
+ bNoDlgs = TRUE;
+ }
+
+ if (strlen(sCmdLine) > 0 && strstr(sCmdLine, "-EMPTYEXIT"))
+ {
+ g_bEmptyExit = TRUE;
+ }
+
+ char configFile[256];
+ strcpy(configFile, "server.cfg");
+
+#ifdef _ADDON
+ LoadString(g_hInst, IDS_CONFIGFILE_AO, configFile, 250);
+#else
+ LoadString(g_hInst, IDS_CONFIGFILE, configFile, 250);
+#endif
+
+ for (i = 0; i < (__argc-1); i++)
+ {
+ if (stricmp(__argv[i], "-CONFIG") == 0)
+ {
+ strncpy(configFile, __argv[i+1], sizeof(configFile));
+ }
+ }
+
+
+ // Check for modifier keys...
+
+ Sleep(50);
+
+ if (IsKeyDown(VK_SHIFT))
+ {
+ bNoDlgs ^= 1;
+ }
+
+
+ // Find our resources...
+
+ FindRezFiles(g_hInst);
+
+ char* sGameRez = GetGameRezFile();
+
+ if (!sGameRez || sGameRez[0] == '\0')
+ {
+ AfxMessageBox(IDS_ERROR_REZFILE);
+ return(FALSE);
+ }
+
+
+ // Do the wizard...
+
+ BOOL bRet = NetStart_DoWizard(g_hInst, &g_ServerInfo, &g_ServerOptions, &g_NetGame, bNoDlgs, configFile);
+ if (!bRet)
+ {
+ return(FALSE);
+ }
+
+
+ // Do the main dialog...
+
+ CGameServDlg dlg;
+ m_pMainWnd = &dlg;
+
+ dlg.SetConfigFilename(configFile);
+ int nResponse = dlg.DoModal();
+ dlg.Clear();
+
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+
+
+ // Save out all the console variables.
+ NetStart_SaveConsoleVars();
+ NetStart_SaveConfigFile(configFile);
+
+ // Free the server library...
+
+ FreeServerDLL();
+
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+
+ return FALSE;
+}
+
+BOOL CCoolServApp::OnIdle(LONG lCount)
+{
+ return CWinApp::OnIdle(lCount);
+}
+
+#define ADDREZ(sBase, sPost) \
+{ \
+ char sRezFile[128]; \
+ wsprintf(sRezFile, "%s%s.rez", sBase, sPost); \
+ strcpy(sTemps[i], sRezFile); \
+ sGame[i] = sTemps[i]; \
+ i++; \
+}
+
+BOOL CCoolServApp::AddResources(CStringList& collRezFiles)
+{
+ // Specify the main resources...
+
+ ServerInterface* pServerMgr = GetServerInterface();
+ if (!pServerMgr) return(FALSE);
+
+ char sTemps[128][128];
+ char* sGame[128];
+ int i = 0;
+
+ char* sGameRez = GetGameRezFile();
+ char* sSoundRez = GetSoundRezFile();
+
+ sGame[i++] = sGameRez;
+ if (sSoundRez && sSoundRez[0] != '\0') sGame[i++] = sSoundRez;
+
+ sGame[i++] = "custom";
+
+
+ // Specify the patch, test, and language resources...
+
+ char sGameRezBase[64] = { "" };
+ LoadString(g_hInst, IDS_REZBASE, sGameRezBase, 60);
+
+ ADDREZ(sGameRezBase, "P");
+ ADDREZ(sGameRezBase, "P2");
+ ADDREZ(sGameRezBase, "P3");
+ ADDREZ(sGameRezBase, "P4");
+ ADDREZ(sGameRezBase, "P5");
+ ADDREZ(sGameRezBase, "P6");
+ ADDREZ(sGameRezBase, "P7");
+ ADDREZ(sGameRezBase, "P8");
+ ADDREZ(sGameRezBase, "P9");
+ ADDREZ(sGameRezBase, "T");
+ ADDREZ(sGameRezBase, "L");
+
+
+ // Specify the add-on rez files if necessary...
+
+#ifdef _ADDON
+ sGame[i++] = "Blood2Nm.rez";
+ sGame[i++] = "Blood2Nm2.rez";
+#endif
+
+
+ // Specify the custom resources...
+
+ POSITION pos = collRezFiles.GetHeadPosition();
+
+ while (pos)
+ {
+ CString sRezFile = collRezFiles.GetNext(pos);
+
+ strcpy(sTemps[i], sRezFile);
+ sGame[i] = sTemps[i];
+ i++;
+ }
+
+
+ // Add the resources...
+
+ char** sResources = sGame;
+ DBOOL db;
+
+ {
+ CWaitCursor wc;
+
+ db = pServerMgr->AddResources(sResources, i);
+ }
+
+ if (db != DTRUE)
+ {
+ AfxMessageBox(IDS_ERROR_LOADREZ);
+ return(FALSE);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
diff --git a/Blood2Serv/CoolServ.dsp b/Blood2Serv/CoolServ.dsp
new file mode 100644
index 0000000..cfbcc57
--- /dev/null
+++ b/Blood2Serv/CoolServ.dsp
@@ -0,0 +1,233 @@
+# Microsoft Developer Studio Project File - Name="CoolServ" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=CoolServ - Win32 Debug AddOn
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "CoolServ.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "CoolServ.mak" CFG="CoolServ - Win32 Debug AddOn"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CoolServ - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "CoolServ - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "CoolServ - Win32 Debug AddOn" (based on "Win32 (x86) Application")
+!MESSAGE "CoolServ - Win32 Release AddOn" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "CoolServ - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\appheaders" /I "..\misc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_REG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 winmm.lib /nologo /subsystem:windows /machine:I386 /out:"Release/Blood2Sv.exe" /libpath:"..\misc"
+
+!ELSEIF "$(CFG)" == "CoolServ - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\appheaders" /I "..\misc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_REG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Blood2Sv.exe" /pdbtype:sept /libpath:"..\misc"
+
+!ELSEIF "$(CFG)" == "CoolServ - Win32 Debug AddOn"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CoolServ"
+# PROP BASE Intermediate_Dir "CoolServ"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "DebugAddOn"
+# PROP Intermediate_Dir "DebugAddOn"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "\proj\de\dist\inc" /I "\proj\de\api" /I "\proj\de\shared" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\appheaders" /I "..\misc" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_ADDON" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_ADDON"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:"Debug/Blood2Sv.exe" /pdbtype:sept
+# ADD LINK32 winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:"DebugAddOn/B2NmSrv.exe" /pdbtype:sept /libpath:"..\misc"
+
+!ELSEIF "$(CFG)" == "CoolServ - Win32 Release AddOn"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "CoolSer0"
+# PROP BASE Intermediate_Dir "CoolSer0"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseAddOn"
+# PROP Intermediate_Dir "ReleaseAddOn"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "\proj\de\dist\inc" /I "\proj\de\api" /I "\proj\de\shared" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\appheaders" /I "..\misc" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_ADDON" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_ADDON"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 winmm.lib /nologo /subsystem:windows /machine:I386 /out:"Release/Blood2Sv.exe"
+# ADD LINK32 winmm.lib /nologo /subsystem:windows /machine:I386 /out:"ReleaseAddOn/B2NmSrv.exe" /libpath:"..\misc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "CoolServ - Win32 Release"
+# Name "CoolServ - Win32 Debug"
+# Name "CoolServ - Win32 Debug AddOn"
+# Name "CoolServ - Win32 Release AddOn"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\CoolServ.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CoolServ.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\GameServDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyGameSpyMgr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NetStart.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RezFind.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ServerUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\Sparam.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\Utils.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\CoolServ.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\bitmap1.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\CoolServ.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\CoolServ.rc2
+# End Source File
+# Begin Source File
+
+SOURCE=.\Res\game1.bmp
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/Blood2Serv/CoolServ.h b/Blood2Serv/CoolServ.h
new file mode 100644
index 0000000..a36b2e1
--- /dev/null
+++ b/Blood2Serv/CoolServ.h
@@ -0,0 +1,56 @@
+// CoolServ.h : main header file for the COOLSERV application
+//
+
+#if !defined(AFX_COOLSERV_H__C6916245_FA1F_11D0_B46B_00A024805738__INCLUDED_)
+#define AFX_COOLSERV_H__C6916245_FA1F_11D0_B46B_00A024805738__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCoolServApp:
+// See CoolServ.cpp for the implementation of this class
+//
+
+class CCoolServApp : public CWinApp
+{
+public:
+ CCoolServApp(LPCTSTR lpszAppName = NULL);
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCoolServApp)
+ public:
+ virtual BOOL InitInstance();
+ virtual BOOL OnIdle(LONG lCount);
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CCoolServApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+public:
+ BOOL AddResources(CStringList& collRezFiles);
+
+};
+
+CCoolServApp* GetTheApp();
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_COOLSERV_H__C6916245_FA1F_11D0_B46B_00A024805738__INCLUDED_)
diff --git a/Blood2Serv/CoolServ.ncb b/Blood2Serv/CoolServ.ncb
new file mode 100644
index 0000000..d0df9bb
--- /dev/null
+++ b/Blood2Serv/CoolServ.ncb
Binary files differ
diff --git a/Blood2Serv/CoolServ.opt b/Blood2Serv/CoolServ.opt
new file mode 100644
index 0000000..cc5be3c
--- /dev/null
+++ b/Blood2Serv/CoolServ.opt
Binary files differ
diff --git a/Blood2Serv/CoolServ.rc b/Blood2Serv/CoolServ.rc
new file mode 100644
index 0000000..03dd68b
--- /dev/null
+++ b/Blood2Serv/CoolServ.rc
@@ -0,0 +1,823 @@
+//Microsoft Developer Studio 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 DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\CoolServ.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\CoolServ.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+NET_GAME DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_NAME,60,35,192,12,ES_AUTOHSCROLL
+ CONTROL "After",IDC_AFTERFRAGS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,58,78,27,10
+ EDITTEXT IDC_FRAGS,88,77,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "After",IDC_AFTERMINUTES,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,58,94,27,10
+ EDITTEXT IDC_MINUTES,88,93,25,12,ES_AUTOHSCROLL | ES_NUMBER |
+ WS_GROUP
+ CONTROL "Bloodbath",IDC_BB,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,171,77,80,10
+ CONTROL "Capture the flag",IDC_CTF,"Button",BS_AUTORADIOBUTTON,
+ 171,87,80,10
+ CONTROL "Teams",IDC_TEAMS,"Button",BS_AUTORADIOBUTTON,171,97,80,
+ 10
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14,WS_GROUP
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "What settings would you like for this game server?",
+ IDC_STATIC,50,10,213,8
+ GROUPBOX "Server Name",IDC_STATIC,50,23,213,30
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "frags",IDC_STATIC,120,78,32,8
+ LTEXT "minutes",IDC_STATIC,120,94,32,8
+ GROUPBOX "Levels End",IDC_STATIC,50,64,105,50
+ GROUPBOX "Game Type",IDC_STATIC,163,64,100,50
+END
+
+NET_GAMELEVELS DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LISTBOX IDC_RETAILLIST,50,35,80,40,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LISTBOX IDC_CUSTOMLIST,50,92,80,40,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Add >",IDC_ADDRETAIL,142,49,35,14
+ PUSHBUTTON "< Remove",IDC_REMOVE,142,77,35,14
+ PUSHBUTTON "Add >",IDC_ADDCUSTOM,142,105,35,14
+ LISTBOX IDC_GAMELIST,183,35,80,85,LBS_NOINTEGRALHEIGHT |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "Save levels",IDC_SAVE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,183,124,80,10
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Finish",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "Which levels would you like to play?",IDC_STATIC,50,10,
+ 213,8
+ LTEXT "Retail Levels:",IDC_STATIC,50,25,80,8
+ LTEXT "Custom Levels:",IDC_STATIC,50,82,80,8
+ LTEXT "Game Levels:",IDC_STATIC,183,25,80,8
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+END
+
+NET_SERVICES DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LISTBOX IDC_SERVICELIST,50,25,213,40,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Communicate with GameSpy (tcp/ip only)",IDC_USEGAMESPY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,92,150,10
+ CONTROL "Update game info for new joiners",IDC_UPDATEINFO,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,60,104,150,10
+ CONTROL "Register server with Blood2 web site (tcp/ip only)",
+ IDC_SERVERREG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,
+ 116,203,10
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14,WS_DISABLED
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "Which networking service you would like to use?",
+ IDC_STATIC,50,10,213,8
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "What information would you like to broadcast?",
+ IDC_STATIC,50,80,213,8
+END
+
+IDD_GAMESERVER DIALOG DISCARDABLE 0, 0, 399, 271
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server v2.1"
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "&Shutdown",IDCANCEL,244,27,50,16
+ PUSHBUTTON "&Next Level",IDC_COMMANDS_NEXTLEVEL,304,27,50,16
+ PUSHBUTTON "&Boot",IDC_PLAYERS_BOOT,70,245,60,14,WS_DISABLED
+ EDITTEXT IDC_CONSOLE_COMMAND,210,245,147,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Clear",IDC_CONSOLE_CLEAR,361,245,25,14
+ GROUPBOX "Server Info",IDC_STATIC,7,7,190,50
+ RTEXT "Name:",IDC_STATIC,12,23,50,8
+ RTEXT "Running Time:",IDC_STATIC,12,33,50,8
+ RTEXT "Net Service:",IDC_STATIC,12,43,50,8
+ GROUPBOX "Game Info",IDC_STATIC,7,63,190,70
+ RTEXT "Players:",IDC_STATIC,12,79,50,8
+ RTEXT "Current Level:",IDC_STATIC,12,89,50,8
+ RTEXT "Next Level:",IDC_STATIC,12,99,50,8
+ RTEXT "Time in Level:",IDC_STATIC,12,109,50,8
+ RTEXT "Level Goal:",IDC_STATIC,12,119,50,8
+ LISTBOX IDC_LEVELS_LIST,211,79,175,48,LBS_NOINTEGRALHEIGHT |
+ LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Players",IDC_STATIC,7,139,190,125
+ LISTBOX IDC_PLAYERS_LIST,16,151,173,90,LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Console",IDC_STATIC,202,139,190,125
+ GROUPBOX "Levels",IDC_STATIC,202,63,190,70
+ GROUPBOX "Commands",IDC_STATIC,202,7,190,50
+ EDITTEXT IDC_CONSOLE_WINDOW,210,151,176,90,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL
+ LTEXT "Static",IDC_SERVER_NAME,64,23,126,8
+ LTEXT "Static",IDC_SERVER_TIME,64,33,126,8
+ LTEXT "Static",IDC_SERVER_SERVICE,64,43,126,8
+ LTEXT "Static",IDC_GAME_PLAYERS,64,79,126,8
+ LTEXT "Static",IDC_GAME_CURLEVEL,64,89,126,8
+ LTEXT "Static",IDC_GAME_NEXTLEVEL,64,99,126,8
+ LTEXT "Static",IDC_GAME_TIME,64,109,126,8
+ LTEXT "Static",IDC_GAME_GOAL,64,119,126,8
+ DEFPUSHBUTTON "Send",IDC_CONSOLE_SEND,175,249,17,7,NOT WS_VISIBLE
+END
+
+NET_REZFILES DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LISTBOX IDC_SOURCELIST,50,35,80,97,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Add >",IDC_ADD,139,60,35,14
+ PUSHBUTTON "< Remove",IDC_REMOVE,139,80,35,14
+ LISTBOX IDC_DESTLIST,183,35,80,95,LBS_NOINTEGRALHEIGHT |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "Which additional rez files would you like to load?",-1,
+ 50,10,213,8
+ LTEXT "Available Rez Files:",-1,50,25,80,8
+ LTEXT "Rez Files to Load:",-1,183,25,80,8
+ CONTROL "GAME",-1,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",-1,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,256,1
+END
+
+NET_OPTIONS DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_MAXPLAYERS,200,37,30,12,ES_AUTOHSCROLL | ES_NUMBER
+ EDITTEXT IDC_PORTNUM,200,53,30,12,ES_AUTOHSCROLL | ES_NUMBER |
+ NOT WS_VISIBLE
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "What options would you like for this game server?",
+ IDC_STATIC,50,10,213,8
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ RTEXT "How many players would you like to allow?",IDC_STATIC,
+ 57,39,140,8
+ RTEXT "What port would you like to host on?",IDC_PORTNUMTEXT,
+ 62,55,134,8,NOT WS_VISIBLE
+ GROUPBOX "Misc",IDC_STATIC,50,25,213,48
+END
+
+SERVER_OPTIONS DIALOG DISCARDABLE 0, 0, 226, 95
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Server Options"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_RUNSPEED,43,22,32,12,ES_AUTOHSCROLL
+ PUSHBUTTON "?",IDC_HELP_RUNSPEED,79,22,14,12
+ EDITTEXT IDC_MISSILESPEED,43,36,32,12,ES_AUTOHSCROLL
+ PUSHBUTTON "?",IDC_HELP_MISSILESPEED,79,36,14,12
+ EDITTEXT IDC_TIMESPEED,153,22,44,12,ES_AUTOHSCROLL
+ PUSHBUTTON "?",IDC_HELP_TIMESPEED,201,22,14,12
+ PUSHBUTTON "Night Color:",IDC_COLORPICKER,109,36,42,12,BS_RIGHT
+ EDITTEXT IDC_NIGHTCOLOR,153,36,44,12,ES_AUTOHSCROLL
+ PUSHBUTTON "?",IDC_HELP_NIGHTCOLOR,201,36,14,12
+ DEFPUSHBUTTON "&OK",IDC_NEXT,55,74,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,121,74,50,14
+ RTEXT "Run:",-1,9,23,32,8
+ RTEXT "Missile:",-1,9,37,32,8
+ RTEXT "Time Speed:",-1,105,23,45,8
+ GROUPBOX "Speeds",-1,7,7,90,50
+ GROUPBOX "World",-1,104,7,115,50
+END
+
+NET_GAMEDAMAGE DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Allow falling damage",IDC_FALLDAMAGE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,70,24,100,10
+ COMBOBOX IDC_HEALRATE,70,64,80,110,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "Would you like to allow falling damage?",IDC_STATIC,50,
+ 10,213,8
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "Which healing rate would you like?",IDC_STATIC,50,50,
+ 213,8
+END
+
+NET_GAMEITEMS DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ COMBOBOX IDC_AMMO_LEVEL,60,35,80,80,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ EDITTEXT IDC_AMMO_RESPAWN,103,52,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ COMBOBOX IDC_ARMOR_LEVEL,173,35,80,80,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_ARMOR_RESPAWN,216,52,25,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ COMBOBOX IDC_HEALTH_LEVEL,60,95,80,80,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_HEALTH_RESPAWN,103,112,25,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ COMBOBOX IDC_POWERUPS_LEVEL,173,95,80,80,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_POWERUPS_RESPAWN,216,112,25,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ GROUPBOX "Ammo",IDC_STATIC,50,20,102,52
+ GROUPBOX "Armor",IDC_STATIC,161,20,102,52
+ GROUPBOX "Health",IDC_STATIC,50,80,102,52
+ GROUPBOX "Powerups",IDC_STATIC,161,80,102,52
+ LTEXT "What items would you like to make available?",
+ IDC_STATIC,50,7,213,8
+ RTEXT "Respawn:",IDC_STATIC,56,54,44,8
+ RTEXT "Respawn:",IDC_STATIC,169,54,44,8
+ RTEXT "Respawn:",IDC_STATIC,56,114,44,8
+ RTEXT "Respawn:",IDC_STATIC,169,114,44,8
+END
+
+NET_OPTIONS_CTF DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Allow friendly fire",IDC_FRIENDLYFIRE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,60,35,140,10
+ CONTROL "Score negative frags for friendly fire",IDC_NEGFRAGS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,70,140,10
+ CONTROL "Only flag capturing scores points",IDC_ONLYFLAGSCORES,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,80,174,10
+ CONTROL "Use enemy team size as flag score multiplier",
+ IDC_USETEAMSIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,
+ 90,193,10
+ EDITTEXT IDC_FLAGVALUE,113,109,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "What CTF-play options would you like?",IDC_STATIC,50,7,
+ 213,8
+ GROUPBOX "Teams",IDC_STATIC,50,20,213,30
+ GROUPBOX "Scoring",IDC_STATIC,50,57,213,75
+ RTEXT "Flag value:",IDC_STATIC,60,110,50,8
+END
+
+NET_OPTIONS_TEAMS DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Allow friendly fire",IDC_FRIENDLYFIRE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,60,40,140,10
+ CONTROL "Score negative frags for friendly fire",IDC_NEGFRAGS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,75,140,10
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "What Team-play options would you like?",IDC_STATIC,50,7,
+ 213,8
+ GROUPBOX "Teams",IDC_STATIC,50,25,213,30
+ GROUPBOX "Scoring",IDC_STATIC,50,62,213,30
+END
+
+NET_GAME_AO DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_NAME,60,38,192,12,ES_AUTOHSCROLL
+ CONTROL "After",IDC_AFTERFRAGS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,58,81,27,10
+ EDITTEXT IDC_FRAGS,88,80,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "After",IDC_AFTERMINUTES,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,58,97,27,10
+ EDITTEXT IDC_MINUTES,88,96,25,12,ES_AUTOHSCROLL | ES_NUMBER |
+ WS_GROUP
+ CONTROL "Bloodbath",IDC_BB,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP,171,77,80,10
+ CONTROL "Capture the flag",IDC_CTF,"Button",BS_AUTORADIOBUTTON,
+ 171,87,80,10
+ CONTROL "Teams",IDC_TEAMS,"Button",BS_AUTORADIOBUTTON,171,97,80,
+ 10
+ CONTROL "Soccer",IDC_SOCCER,"Button",BS_AUTORADIOBUTTON,171,107,
+ 80,10
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14,WS_GROUP
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ LTEXT "What settings would you like for this game session?",
+ IDC_STATIC,50,10,213,8
+ GROUPBOX "Session Name",IDC_STATIC,50,26,213,30
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "frags",IDC_STATIC,120,81,32,8
+ LTEXT "minutes",IDC_STATIC,120,97,32,8
+ GROUPBOX "Levels End",IDC_STATIC,50,64,105,55
+ GROUPBOX "Game Type",IDC_STATIC,163,64,100,55
+END
+
+NET_OPTIONS_SOCCER DIALOG DISCARDABLE 0, 0, 270, 170
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Blood2 Multiplayer Wizard"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Allow friendly fire",IDC_FRIENDLYFIRE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,60,35,75,10
+ CONTROL "Soccer ball skin",IDC_SKIN_SOCCER,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,168,35,80,10
+ CONTROL "Zombie head skin",IDC_SKIN_ZOMBIE,"Button",
+ BS_AUTORADIOBUTTON,168,45,80,10
+ CONTROL "Score negative frags for friendly fire",IDC_NEGFRAGS,
+ "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,60,80,
+ 140,10
+ CONTROL "Only scoring goals scores points",IDC_ONLYGOALSCORES,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,90,174,10
+ CONTROL "Use enemy team size as goal score multiplier",
+ IDC_USETEAMSIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,
+ 100,193,10
+ EDITTEXT IDC_GOALVALUE,113,115,25,12,ES_AUTOHSCROLL | ES_NUMBER
+ PUSHBUTTON "< &Back",IDC_BACK,85,149,50,14
+ DEFPUSHBUTTON "&Next >",IDC_NEXT,135,149,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,213,149,50,14
+ CONTROL "GAME",IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ WS_BORDER,7,7,36,125
+ CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME | SS_SUNKEN,7,142,
+ 256,1
+ LTEXT "What soccer options would you like?",IDC_STATIC,50,7,
+ 213,8
+ GROUPBOX "Teams",IDC_STATIC,50,20,100,40
+ GROUPBOX "Scoring",IDC_STATIC,50,67,213,65
+ RTEXT "Goal value:",IDC_STATIC,60,116,50,8
+ GROUPBOX "Soccer Ball",IDC_STATIC,158,20,105,40
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "monolith@lith.com\0"
+ VALUE "CompanyName", "Monolith Productions Inc.\0"
+ VALUE "FileDescription", "Blood2 Stand-Alone Server\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "Blood2Serv\0"
+ VALUE "LegalCopyright", "Copyright (C) 1998, Monolith Productions, Inc.\0"
+ VALUE "OriginalFilename", "Blood2Sv.exe\0"
+ VALUE "ProductName", "Blood2Serv\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ "NET_GAME", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_GAMELEVELS", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_SERVICES", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ IDD_GAMESERVER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 392
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 264
+ END
+
+ "NET_REZFILES", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_OPTIONS", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "SERVER_OPTIONS", DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 219
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+
+ "NET_GAMEDAMAGE", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_GAMEITEMS", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_OPTIONS_CTF", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_OPTIONS_TEAMS", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_GAME_AO", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+
+ "NET_OPTIONS_SOCCER", DIALOG
+ BEGIN
+ LEFTMARGIN, 50
+ RIGHTMARGIN, 263
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 163
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+#if defined(APSTUDIO_INVOKED) || defined(_REG)
+#if defined(APSTUDIO_INVOKED)
+GAME$(_REG) BITMAP DISCARDABLE "bitmap1.bmp"
+#else
+GAME BITMAP DISCARDABLE "bitmap1.bmp"
+#endif
+#endif
+#if defined(APSTUDIO_INVOKED) || defined(_ADDON)
+#if defined(APSTUDIO_INVOKED)
+GAME$(_ADDON) BITMAP DISCARDABLE "res\\game1.bmp"
+#else
+GAME BITMAP DISCARDABLE "res\\game1.bmp"
+#endif
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+NET_GAMEITEMS DLGINIT
+BEGIN
+ IDC_AMMO_LEVEL, 0x403, 5, 0
+0x6f4e, 0x656e, "\000"
+ IDC_AMMO_LEVEL, 0x403, 5, 0
+0x6148, 0x666c, "\000"
+ IDC_AMMO_LEVEL, 0x403, 7, 0
+0x6f4e, 0x6d72, 0x6c61, "\000"
+ IDC_AMMO_LEVEL, 0x403, 7, 0
+0x6f44, 0x6275, 0x656c, "\000"
+ IDC_AMMO_LEVEL, 0x403, 7, 0
+0x6e49, 0x6173, 0x656e, "\000"
+ IDC_AMMO_LEVEL, 0x403, 10, 0
+0x6e55, 0x696c, 0x696d, 0x6574, 0x0064,
+ IDC_ARMOR_LEVEL, 0x403, 5, 0
+0x6f4e, 0x656e, "\000"
+ IDC_ARMOR_LEVEL, 0x403, 5, 0
+0x6148, 0x666c, "\000"
+ IDC_ARMOR_LEVEL, 0x403, 7, 0
+0x6f4e, 0x6d72, 0x6c61, "\000"
+ IDC_ARMOR_LEVEL, 0x403, 7, 0
+0x6f44, 0x6275, 0x656c, "\000"
+ IDC_ARMOR_LEVEL, 0x403, 7, 0
+0x6e49, 0x6173, 0x656e, "\000"
+ IDC_ARMOR_LEVEL, 0x403, 10, 0
+0x6e55, 0x696c, 0x696d, 0x6574, 0x0064,
+ IDC_HEALTH_LEVEL, 0x403, 5, 0
+0x6f4e, 0x656e, "\000"
+ IDC_HEALTH_LEVEL, 0x403, 5, 0
+0x6148, 0x666c, "\000"
+ IDC_HEALTH_LEVEL, 0x403, 7, 0
+0x6f4e, 0x6d72, 0x6c61, "\000"
+ IDC_HEALTH_LEVEL, 0x403, 7, 0
+0x6f44, 0x6275, 0x656c, "\000"
+ IDC_HEALTH_LEVEL, 0x403, 7, 0
+0x6e49, 0x6173, 0x656e, "\000"
+ IDC_HEALTH_LEVEL, 0x403, 10, 0
+0x6e55, 0x696c, 0x696d, 0x6574, 0x0064,
+ IDC_POWERUPS_LEVEL, 0x403, 5, 0
+0x6f4e, 0x656e, "\000"
+ IDC_POWERUPS_LEVEL, 0x403, 5, 0
+0x6148, 0x666c, "\000"
+ IDC_POWERUPS_LEVEL, 0x403, 7, 0
+0x6f4e, 0x6d72, 0x6c61, "\000"
+ IDC_POWERUPS_LEVEL, 0x403, 7, 0
+0x6f44, 0x6275, 0x656c, "\000"
+ IDC_POWERUPS_LEVEL, 0x403, 7, 0
+0x6e49, 0x6173, 0x656e, "\000"
+ IDC_POWERUPS_LEVEL, 0x403, 10, 0
+0x6e55, 0x696c, 0x696d, 0x6574, 0x0064,
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ERROR_REZFILE "ERROR - Unable to access the Blood2 game resources. Please make sure Blood2 is installed properly and try again."
+ IDS_ERROR_LOADREZ "ERROR - Unable to load Blood2 resources."
+ IDS_ERROR_LOADSERVER "ERROR - Unable to load SERVER.DLL."
+ IDS_ERROR_ACCESSSERVER "ERROR - Unable to access SERVER.DLL."
+ IDS_ERROR_MEMORY "ERROR - Out of memory. The Blood2 server will be shutdown."
+ IDS_HELP_RUNSPEED "Multiplies the player's run speed.\n\nDefault value is 1.0."
+ IDS_TITLE_RUNSPEED "Server Option: Run Speed"
+ IDS_HELP_MISSILESPEED "Multiplies the missile speed.\n\nDefault value is 1.0."
+ IDS_TITLE_MISSILESPEED "Server Option: Missile Speed"
+ IDS_HELP_TIMESPEED "Multiplies the time speed of the world.\n\nDefault value is 1.0. A value of -1 makes time stand still."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_DEFAULTSERVERNAME "Blood2 Server"
+ IDS_SPYGAMENAME "blood2"
+ IDS_GAMETYPE_DEATHMATCH "Bloodbath"
+ IDS_SPYGAMEVER "blood2 2.1"
+ IDS_SPYGAMEKEY "jUOF0p"
+ IDS_WEBGAMENAME "Blood2"
+ IDS_WEBGAMEVER "2.1"
+ IDS_GAMETYPE_UNKNOWN "Unknown"
+ IDS_GAMETYPE_CAPTUREFLAG "Capture the flag"
+ IDS_GAMETYPE_COOPERATIVE "Cooperative"
+ IDS_GAMETYPE_TEAM "Teams"
+ IDS_GAMETYPE_SOCCER "Soccer"
+ IDS_GAMETYPE_TOETAG "Toe Tag"
+ IDS_WEBREGURL "http://www.the-chosen.com/servers/server.asp"
+ IDS_NEXTLEVEL "Preparing to load the next level..."
+ IDS_DEFAULTSERVERNAME_AO "Blood2 Nightmares Server"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_NETERR_GENERIC "ERROR - Unable to setup the network game server."
+ IDS_NETERR_SELECTSERVICE
+ "ERROR - Unable to use the selected network service."
+ IDS_NETERR_FILLSERVICE "ERROR - Unable to access the available network services."
+ IDS_NETERR_JOINSESSION "ERROR - Unable to join the selected game session."
+ IDS_NETERR_HOSTSESSION "ERROR - Unable to host the game session."
+ IDS_NETERR_INIT "ERROR - Unable to initialize the networking system."
+ IDS_REZBASE "blood2"
+ IDS_APPNAME "Blood2Sv"
+ IDS_CONFIGFILE "Blood2Sv.cfg"
+ IDS_APPNAME_AO "Blood2 Nightmares Server"
+ IDS_CONFIGFILE_AO "B2NmSrv.cfg"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_TITLE_TIMESPEED "Server Option: World Time Speed"
+ IDS_HELP_NIGHTCOLOR "Specifies the color of the night sky in red, green, and blue float value components (from 0.0 to 1.0). You can click the ""Night Color"" button to bring up a color picker dialog.\n\nDefault value is ""0.5 0.5 0.5""."
+ IDS_TITLE_NIGHTCOLOR "Server Option: World Night Color"
+ IDS_HELP_RESPAWNSCALE "Multiplies the respawn rate of items.\n\nDefault value is 1.0."
+ IDS_TITLE_RESPAWNSCALE "Server Option: Respawn Scale"
+ IDS_HELP_HEALSCALE "Scales how much health the health powerups give players.\n\nDefault value is 1.0."
+ IDS_TITLE_HEALSCALE "Server Option: Heal Scale"
+ IDS_TITLE_DASHGO "Blood2 Server"
+ IDS_HELP_DASHGO "Power users can specify the ""-go"" command-line parameter when running Blood2Sv to skip all the dialogs (the previous settings will be used).\n\nFor more information about Blood2Sv, please view the Blood2Sv.txt file."
+ IDS_CHECKEXIT "Are you sure you want to exit?"
+ IDS_CONSOLE_INITSERVER "Initializing the server..."
+ IDS_CONSOLE_SERVERINITED "Server initialized."
+ IDS_CONSOLE_UNABLETOHOST "ERROR - Unable to host the game."
+ IDS_CONSOLE_SERVERRUNNING "Server is running."
+ IDS_CONSOLE_LASTPLAYERLEFT "Last player has left, shutting down..."
+ IDS_CONSOLE_UNABLETOSTARTWORLD "ERROR - Unable to start world:"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_NETWIZ_ITEMS_NONE "None"
+ IDS_NETWIZ_ITEMS_HALF "Half"
+ IDS_NETWIZ_ITEMS_NORMAL "Normal"
+ IDS_NETWIZ_ITEMS_DOUBLE "Double"
+ IDS_NETWIZ_ITEMS_INSANE "Insane"
+ IDS_NETWIZ_HEAL_NOHEALING "No Healing"
+ IDS_NETWIZ_HEAL_REALLYSLOW "Really Slow"
+ IDS_NETWIZ_HEAL_SLOW "Slow"
+ IDS_NETWIZ_HEAL_NORMAL "Normal"
+ IDS_NETWIZ_HEAL_FAST "Fast"
+ IDS_NETWIZ_HEAL_REALLYFAST "Really Fast"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_SPYGAMEVER_AO "nightmares 1.0"
+ IDS_WEBGAMENAME_AO "Blood2 Nightmares"
+ IDS_WEBGAMEVER_AO "1.0"
+ IDS_DIALOGTITLE_AO "Blood2 Nightmares Server 1.0"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "res\CoolServ.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Blood2Serv/GameServDlg.cpp b/Blood2Serv/GameServDlg.cpp
new file mode 100644
index 0000000..bf476f0
--- /dev/null
+++ b/Blood2Serv/GameServDlg.cpp
@@ -0,0 +1,1478 @@
+// GameServDlg.cpp : implementation file
+//
+
+
+// Includes...
+
+#include "stdafx.h"
+#include "coolserv.h"
+#include "GameServDlg.h"
+#include "NetStart.h"
+#include "Sparam.h"
+#include "Utils.h"
+#include "mmsystem.h"
+
+
+// Defines...
+
+#define DEFAULT_PORT 27888
+#define USE_POSTMSG 0
+
+
+// Debug...
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+// Macros...
+
+#define DEC_TIMER(t, d) if (d >= t) t = 0; else t -= d;
+
+
+// Externs...
+
+extern ServerInfo g_ServerInfo;
+extern ServerOptions g_ServerOptions;
+extern NetGame g_NetGame;
+extern BOOL g_bEmptyExit;
+
+
+// Globals...
+
+DWORD g_timeCur = 0;
+DWORD g_timeLast = 0;
+DWORD g_timeDelta = 0;
+DWORD g_timeStart = 0;
+
+DWORD g_dwPosted = 0;
+DWORD g_dwHandled = 0;
+DWORD g_dwRemoved = 0;
+
+BOOL g_bDoEmptyExit = FALSE;
+int g_nEmptyExitDelay = 60;
+DWORD g_timerEmptyExit = 0;
+BOOL g_bNoExitConfirm = FALSE;
+
+CString g_sFullTcpIpAddress;
+WORD g_wPort = 0;
+
+#define SERVER_VERSION "2.1"
+#define DEFAULT_PORT 27888
+
+CString g_sSpyGameName;
+CString g_sSpyGameVer;
+CString g_sSpyGameKey;
+CString g_sWebGameName;
+CString g_sWebGameVer;
+CString g_sWebRegUrl;
+
+
+// Statics...
+
+static DWORD s_timerWebRegUpdate = 400;
+
+static BOOL s_bThreadDone = FALSE;
+
+
+// Classes...
+
+class CGameServerAppHandler : public ServerAppHandler
+{
+public:
+ DRESULT ShellMessageFn(char* pInfo);
+ DRESULT ConsoleOutputFn(char* pInfo);
+ DRESULT OutOfMemory();
+ DRESULT ProcessPacket(char *pData, DDWORD dataLen, DBYTE senderAddr[4], D_WORD senderPort);
+};
+
+
+// Globals...
+
+CGameServDlg* g_pDialog = NULL;
+CGameServerAppHandler g_AppHandler;
+
+
+// Prototypes...
+
+DWORD WINAPI ThreadUpdate(LPVOID lpParameter);
+
+
+// Functions...
+
+DRESULT CGameServerAppHandler::ShellMessageFn(char* pInfo)
+{
+ if (g_pDialog)
+ {
+ g_pDialog->OnShellMessage(pInfo);
+ }
+
+ return(LT_OK);
+}
+
+DRESULT CGameServerAppHandler::ConsoleOutputFn(char* pInfo)
+{
+ if (g_pDialog)
+ {
+ g_pDialog->OnConsoleOutput(pInfo);
+ }
+
+ return(LT_OK);
+}
+
+DRESULT CGameServerAppHandler::OutOfMemory()
+{
+ if (g_pDialog)
+ {
+ g_pDialog->OnOutOfMemory();
+ }
+
+ return(LT_OK);
+}
+
+DRESULT CGameServerAppHandler::ProcessPacket(char *pData, DDWORD dataLen, DBYTE senderAddr[4], D_WORD senderPort)
+{
+ if(g_pDialog)
+ {
+ g_pDialog->OnProcessNetPacket(pData, dataLen, senderAddr, senderPort);
+ }
+
+ return LT_OK;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------- //
+// Replacement for MFC's trace. Doesn't ASSERT.
+// ----------------------------------------------------------------------- //
+
+void SS_Trace(const char *pMsg, ...)
+{
+ #ifdef _DEBUG
+ char buf[1024*16];
+ va_list marker;
+
+ va_start(marker, pMsg);
+ vsprintf(buf, pMsg, marker);
+ va_end(marker);
+
+ OutputDebugString(buf);
+ #endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CGameServSendHandler
+/////////////////////////////////////////////////////////////////////////////
+
+void CGameServSendHandler::SendTo(const void *pData, unsigned long len, const char *sAddr, unsigned long port)
+{
+ ServerInterface *pMgr;
+
+ if(m_pDlg && (pMgr = m_pDlg->GetServerMgr()))
+ {
+ pMgr->SendTo(pData, len, sAddr, port);
+ }
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CGameServDlg dialog
+
+CGameServDlg::CGameServDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CGameServDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CGameServDlg)
+ //}}AFX_DATA_INIT
+
+ Clear();
+
+ m_pConfigFilename = NULL;
+ g_pDialog = this;
+ m_SendHandler.SetDlg(this);
+
+ m_sGameSpyGameMode = "openplaying";
+ m_sGameSpyGameType = "deathmatch";
+}
+
+
+void CGameServDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CGameServDlg)
+ DDX_Control(pDX, IDC_PLAYERS_LIST, m_lbPlayers);
+ DDX_Control(pDX, IDC_LEVELS_LIST, m_lbLevels);
+ DDX_Control(pDX, IDC_CONSOLE_WINDOW, m_edConsole);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CGameServDlg, CDialog)
+ //{{AFX_MSG_MAP(CGameServDlg)
+ ON_WM_SHOWWINDOW()
+ ON_WM_CLOSE()
+ ON_WM_TIMER()
+ ON_BN_CLICKED(IDC_QUIT, OnQuit)
+ ON_BN_CLICKED(IDC_SERVER, OnServer)
+ ON_BN_CLICKED(IDC_CONSOLE_SEND, OnConsoleSend)
+ ON_BN_CLICKED(IDC_CONSOLE_CLEAR, OnConsoleClear)
+ ON_BN_CLICKED(IDC_COMMANDS_NEXTLEVEL, OnCommandsNextLevel)
+ ON_BN_CLICKED(IDC_PLAYERS_BOOT, OnPlayersBoot)
+ ON_LBN_SELCHANGE(IDC_PLAYERS_LIST, OnSelchangePlayersList)
+ ON_WM_DESTROY()
+ ON_BN_CLICKED(IDC_COMMANDS_OPTIONS, OnCommandsOptions)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+BOOL CGameServDlg::Init()
+{
+ if(!m_bCSInitted)
+ {
+ InitializeCriticalSection(&m_CS);
+ m_bCSInitted = TRUE;
+ }
+
+ // Display a console message...
+
+ WriteConsoleString(IDS_CONSOLE_INITSERVER);
+
+
+ // Get the server interface...
+
+ m_pServerMgr = GetServerInterface();
+ if (!m_pServerMgr) return(FALSE);
+
+
+ // Set our app handler...
+
+ m_pServerMgr->SetAppHandler(&g_AppHandler);
+
+
+ // Set the tab stops for the player list box...
+
+ int nTabs[10] = { 30, 116, 181, 84, 86, 88, 90, 92, 94, 96 };
+
+ m_lbPlayers.SetTabStops(10, nTabs);
+
+
+ // Load some strings...
+
+ g_sSpyGameName.LoadString(IDS_SPYGAMENAME);
+ g_sSpyGameKey.LoadString(IDS_SPYGAMEKEY);
+ g_sWebRegUrl.LoadString(IDS_WEBREGURL);
+
+#ifdef _ADDON
+ g_sSpyGameVer.LoadString(IDS_SPYGAMEVER_AO);
+ g_sWebGameName.LoadString(IDS_WEBGAMENAME_AO);
+ g_sWebGameVer.LoadString(IDS_WEBGAMEVER_AO);
+#else
+ g_sSpyGameVer.LoadString(IDS_SPYGAMEVER);
+ g_sWebGameName.LoadString(IDS_WEBGAMENAME);
+ g_sWebGameVer.LoadString(IDS_WEBGAMEVER);
+#endif
+
+
+ // All done...
+
+ WriteConsoleString(IDS_CONSOLE_SERVERINITED);
+ return(TRUE);
+}
+
+void CGameServDlg::Term()
+{
+ if(m_bCSInitted)
+ {
+ DeleteCriticalSection(&m_CS);
+ m_bCSInitted = FALSE;
+ }
+
+ Clear();
+ g_pDialog = NULL;
+
+ Sleep(2);
+ SS_Trace("Updates posted = %lu\n", g_dwPosted);
+ SS_Trace("Updates handled = %lu\n", g_dwHandled);
+ SS_Trace("Updates removed = %lu\n", g_dwRemoved);
+ SS_Trace("Updates per sec = %i\n", (int)((float)(g_dwHandled / (float)(timeGetTime() - g_timeStart)) * 1000));
+}
+
+void CGameServDlg::Clear()
+{
+ m_bCSInitted = FALSE;
+ memset(&m_CS, 0, sizeof(m_CS));
+
+ m_pServerMgr = NULL;
+ g_pDialog = NULL;
+
+ m_bRunning = FALSE;
+ m_bLevelChanging = FALSE;
+
+ m_timeServerRunning = 0;
+ m_timeServerStart = 0;
+ m_timeServerLast = 0;
+
+ m_timeLevelRunning = 0;
+ m_timeLevelStart = 0;
+ m_timeLevelLast = 0;
+
+ m_cPlayers = 0;
+ m_nCurLevel = 0;
+
+ m_hThread = NULL;
+ m_dwThreadID = NULL;
+
+ m_sCurLevel.Empty();
+}
+
+BOOL CGameServDlg::StartServer()
+{
+ // Sanity checks...
+
+ if (!m_pServerMgr) return(FALSE);
+
+
+ // Set the debug level...
+
+ m_pServerMgr->RunConsoleString("debuglevel 0");
+
+
+ // Set the server options...
+
+ NetStart_RunServerOptions(m_pServerMgr, &g_ServerOptions);
+
+
+ // Set the game type string based on the game type...
+
+ int nStringID = IDS_GAMETYPE_DEATHMATCH;
+
+ switch (g_NetGame.m_byType)
+ {
+ case NGT_CAPTUREFLAG: nStringID = IDS_GAMETYPE_CAPTUREFLAG; break;
+ case NGT_COOPERATIVE: nStringID = IDS_GAMETYPE_COOPERATIVE; break;
+ case NGT_TEAMS: nStringID = IDS_GAMETYPE_TEAM; break;
+
+#ifdef _ADDON
+ case NGT_SOCCER: nStringID = IDS_GAMETYPE_SOCCER; break;
+#endif
+
+ }
+
+ m_sGameSpyGameType.LoadString(nStringID);
+
+
+ // Look at some console vars...
+
+ HCONSOLEVAR hVar = NULL;
+
+ DRESULT dr = m_pServerMgr->GetConsoleVar("WebRegUpdate", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ float fVal = 0;
+ dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
+ if (dr == LT_OK && fVal > 1)
+ {
+ s_timerWebRegUpdate = (DWORD)fVal;
+ }
+ }
+
+ hVar = NULL;
+ dr = m_pServerMgr->GetConsoleVar("EmptyExit", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ float fVal = 0;
+ dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
+ if (dr == LT_OK && fVal >= 1)
+ {
+ g_bEmptyExit = TRUE;
+ }
+ }
+
+ hVar = NULL;
+ dr = m_pServerMgr->GetConsoleVar("EmptyExitDelay", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ float fVal = 0;
+ dr = m_pServerMgr->GetVarValueFloat(hVar, &fVal);
+ if (dr == LT_OK && fVal >= 1)
+ {
+ g_nEmptyExitDelay = (int)fVal;
+ }
+ }
+
+ hVar = NULL;
+ dr = m_pServerMgr->GetConsoleVar("SpyGameType", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ char sTemp[64] = { "" };
+ dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
+ if (dr == LT_OK && sTemp[0] != '\0')
+ {
+ m_sGameSpyGameType = sTemp;
+ }
+ }
+
+ hVar = NULL;
+ dr = m_pServerMgr->GetConsoleVar("SpyGameMode", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ char sTemp[64] = { "" };
+ dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
+ if (dr == LT_OK && sTemp[0] != '\0')
+ {
+ m_sGameSpyGameMode = sTemp;
+ }
+ }
+
+
+ // Host the game...
+
+ CWaitCursor wc;
+
+ NetHost nh;
+
+ memset(&nh, 0, sizeof(nh));
+
+ nh.m_dwMaxPlayers = g_ServerInfo.m_dwMaxPlayers;
+ nh.m_Port = NetStart_GetPort();
+
+ CString sHost;
+
+#ifdef _ADDON
+ sHost.LoadString(IDS_APPNAME_AO);
+#else
+ sHost.LoadString(IDS_APPNAME);
+#endif
+
+ Sparam_Add(nh.m_sName, NST_GAMENAME, g_ServerInfo.m_sName);
+ Sparam_Add(nh.m_sName, NST_GAMEHOST, sHost);
+ Sparam_Add(nh.m_sName, NST_GAMELEVEL, g_NetGame.m_sLevels[0]);
+ Sparam_Add(nh.m_sName, NST_GAMETYPE, g_NetGame.m_byType);
+
+ if (m_pServerMgr->HostGame(&nh) != DTRUE)
+ {
+ WriteConsoleString(IDS_CONSOLE_UNABLETOHOST);
+ StopServer();
+ return(FALSE);
+ }
+
+
+ // Start the world...
+
+ StartGameRequest req;
+ memset(&req, 0, sizeof(req));
+
+ req.m_Type = STARTGAME_HOST;
+ req.m_pGameInfo = &g_NetGame;
+ req.m_GameInfoLen = sizeof(NetGame_t);
+
+ strcpy(req.m_WorldName, g_NetGame.m_sLevels[0]);
+
+ if (m_pServerMgr->StartWorld(&req) != DTRUE)
+ {
+ WriteConsoleString(IDS_CONSOLE_UNABLETOSTARTWORLD);
+ WriteConsoleString(req.m_WorldName);
+ StopServer();
+ return(FALSE);
+ }
+
+
+ // Update the service info with the tcp/ip address if available...
+
+ g_ServerInfo.m_sAddress[0] = '\0';
+ g_wPort = 0;
+
+ m_pServerMgr->GetTcpIpAddress(g_ServerInfo.m_sAddress, 128, g_wPort);
+
+ CString sService = g_ServerInfo.m_sService;
+ g_sFullTcpIpAddress = "";
+ if (g_ServerInfo.m_sAddress[0] != '\0')
+ {
+ sService += " ";
+ g_sFullTcpIpAddress = g_ServerInfo.m_sAddress;
+ if (g_wPort > 0 && g_wPort != DEFAULT_PORT)
+ {
+ char sTemp[32];
+ wsprintf(sTemp, ":%i", g_wPort);
+ g_sFullTcpIpAddress += sTemp;
+ }
+ sService += "[";
+ sService += g_sFullTcpIpAddress;
+ sService += "]";
+ }
+ SetDlgItemText(IDC_SERVER_SERVICE, sService);
+
+
+ // Tell the server shell to update the game info parameters...
+
+ m_pServerMgr->SendToServerShell("GAMEINIT");
+
+
+ // Tell the server that this is a stand-alone server hosted game...
+
+ m_pServerMgr->SendToServerShell("SERVHOST");
+
+
+ // Init some stuff now that we're running...
+
+ m_bRunning = TRUE;
+ m_timeServerStart = timeGetTime();
+ g_timeStart = timeGetTime();
+ m_timeLevelStart = m_timeServerStart;
+
+
+ // Init the GameSpy manager...
+
+ if (g_ServerInfo.m_bUseGameSpy)
+ {
+ if (m_GameSpyMgr.Init(g_sSpyGameName, g_sSpyGameVer, g_sSpyGameKey, 0, g_wPort, (g_wPort+166), GSMF_USEGAMEPORTFORHEARTBEAT))
+ {
+ m_GameSpyMgr.SetSendHandler(&m_SendHandler);
+ }
+ else
+ {
+ g_ServerInfo.m_bUseGameSpy = FALSE;
+ }
+ }
+
+
+ // Create the thread to do our updating...
+
+ m_hThread = CreateThread(NULL, 0, ThreadUpdate, (void*)g_pDialog, 0, &m_dwThreadID);
+
+
+ // All done...
+
+ WriteConsoleString(IDS_CONSOLE_SERVERRUNNING);
+ return(TRUE);
+}
+
+BOOL CGameServDlg::StopServer()
+{
+ // Unregister the server if necessary...
+
+ if (m_bRunning)
+ {
+ UnregisterServer();
+ }
+
+
+ // Terminate the GameSpy manager...
+
+ m_GameSpyMgr.Term();
+
+
+ // Flag that we are done...
+
+ m_bRunning = FALSE;
+
+
+ // Wait for the thread to stop...
+
+ if (m_hThread)
+ {
+ Sleep(0);
+ DWORD dwRet = WaitForSingleObject(m_hThread, 1000);
+ Sleep(0);
+
+ if (dwRet == WAIT_OBJECT_0)
+ {
+ CloseHandle(m_hThread);
+ }
+ else
+ {
+ TerminateThread(m_hThread, 0);
+ }
+
+ m_hThread = NULL;
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+void CGameServDlg::WriteConsoleString(LPCTSTR pMsg, ...)
+{
+ TCHAR str[500];
+ va_list marker;
+ int nLen;
+
+ static int nMax = 500;
+
+ if(m_edConsole.GetLineCount() > nMax)
+ {
+ // Nuke the oldest 75%.
+ int iLine = (m_edConsole.GetLineCount()*75) / 100;
+ int iChar = m_edConsole.LineIndex(iLine);
+
+ m_edConsole.SetRedraw(FALSE);
+ m_edConsole.SetSel(0, iChar);
+ m_edConsole.ReplaceSel("", FALSE);
+ m_edConsole.SetRedraw(TRUE);
+ }
+
+ va_start(marker, pMsg);
+ vsprintf(str, pMsg, marker);
+ va_end(marker);
+
+ int len = strlen(str);
+ if (len <= 0) return;
+ if (len > 0 && str[len-1] < 32) str[len-1] = '\0';
+
+ strcat(str, "\r\n");
+
+ nLen = m_edConsole.SendMessage(EM_GETLIMITTEXT, 0, 0);
+ m_edConsole.SetSel(nLen, nLen);
+ m_edConsole.ReplaceSel(str);
+}
+
+void CGameServDlg::WriteConsoleString(int nStringID)
+{
+ CString sMsg;
+ if (!sMsg.LoadString(nStringID)) return;
+ WriteConsoleString(sMsg);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CGameServDlg message handlers
+
+BOOL CGameServDlg::OnInitDialog()
+{
+ // Let the base class do it's thing...
+
+ CDialog::OnInitDialog();
+
+
+ // Set the window title if necessary...
+
+#ifdef _ADDON
+ CString sTitle;
+ sTitle.LoadString(IDS_DIALOGTITLE_AO);
+ SetWindowText(sTitle);
+#endif
+
+
+ // Fill in some of the text info...
+
+ SetDlgItemText(IDC_SERVER_NAME, g_ServerInfo.m_sName);
+ SetDlgItemText(IDC_SERVER_TIME, "0:00");
+
+ CString sService(g_ServerInfo.m_sService);
+ if (g_ServerInfo.m_sAddress[0] != '\0')
+ {
+ sService += " (";
+ sService += g_ServerInfo.m_sAddress;
+ sService += ")";
+ }
+ SetDlgItemText(IDC_SERVER_SERVICE, sService);
+
+ SetDlgItemText(IDC_GAME_PLAYERS, "0");
+ SetDlgItemText(IDC_GAME_CURLEVEL, g_NetGame.m_sLevels[0]);
+ SetDlgItemText(IDC_GAME_TIME, "0:00");
+
+ m_sCurLevel = g_NetGame.m_sLevels[0];
+
+ if (g_NetGame.m_byNumLevels > 1) SetDlgItemText(IDC_GAME_NEXTLEVEL, g_NetGame.m_sLevels[1]);
+ else SetDlgItemText(IDC_GAME_NEXTLEVEL, "");
+
+ CString sBuf;
+ if (g_NetGame.m_byEnd == NGE_FRAGS) sBuf.Format("%i Frags", g_NetGame.m_dwEndFrags);
+ else if (g_NetGame.m_byEnd == NGE_TIME) sBuf.Format("%i Minutes", g_NetGame.m_dwEndTime);
+ else if (g_NetGame.m_byEnd == NGE_FRAGSANDTIME) sBuf.Format("%i Frags or %i Minutes", g_NetGame.m_dwEndFrags, g_NetGame.m_dwEndTime);
+ else sBuf = "None. Level never ends.";
+ SetDlgItemText(IDC_GAME_GOAL, sBuf);
+
+ for (int i = 0; i < g_NetGame.m_byNumLevels; i++)
+ {
+ m_lbLevels.AddString(g_NetGame.m_sLevels[i]);
+ }
+
+
+ // Set the icon...
+
+ HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+ SetIcon(hIcon, TRUE);
+ SetIcon(hIcon, FALSE);
+
+
+ for(i=0; i < 30; i++)
+ {
+ if(SetTimer((UINT)i, 500, NULL))
+ break;
+ }
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL CGameServDlg::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam)
+ {
+ case ID_INIT:
+ {
+ if (!Init())
+ {
+ return(TRUE);
+ }
+
+ if (!StartServer())
+ {
+ return(TRUE);
+ }
+
+ return(TRUE);
+ }
+
+ case ID_UPDATE:
+ {
+ OnUpdate();
+ return(TRUE);
+ }
+ }
+
+ return(CDialog::OnCommand(wParam, lParam));
+}
+
+void CGameServDlg::OnShowWindow(BOOL bShow, UINT nStatus)
+{
+ static BOOL bNeedInit = TRUE;
+
+ CDialog::OnShowWindow(bShow, nStatus);
+
+ if (bShow && bNeedInit)
+ {
+ bNeedInit = FALSE;
+ PostMessage(WM_COMMAND, ID_INIT);
+ }
+}
+
+void CGameServDlg::UpdateServerMgr(DWORD timeDelta)
+{
+ // Sanity checks...
+
+ if (!m_pServerMgr) return;
+ if (!IsRunning()) return;
+
+
+ // Let the server update...
+
+ if (m_pServerMgr->Update(0) != DTRUE)
+ {
+ WriteServerError();
+ StopServer();
+ }
+}
+
+void CGameServDlg::WriteServerError()
+{
+ char str[256];
+
+ if (m_pServerMgr)
+ {
+ m_pServerMgr->GetErrorString(str, sizeof(str)-1);
+ WriteConsoleString(str);
+ }
+}
+
+void CGameServDlg::OnClose()
+{
+ CDialog::OnClose();
+}
+
+void CGameServDlg::OnTimer(UINT nIDEvent)
+{
+ // Call the update function...
+
+ //OnUpdate();
+ UpdateTimers();
+}
+
+
+void CGameServDlg::OnUpdate()
+{
+ // Increment our counter...
+
+ g_dwHandled++;
+
+
+ // If we're currently changing levels, just return...
+
+ if (IsLevelChanging()) return;
+
+
+ // Get the current time...
+
+ g_timeCur = timeGetTime();
+ if (g_timeLast == 0) g_timeLast = g_timeCur;
+
+
+ // Calculate the delta time...
+
+ g_timeDelta = g_timeCur - g_timeLast;
+ g_timeLast = g_timeCur;
+
+
+ // Update everything if we're running...
+
+ if (IsRunning())
+ {
+ // Update the empty exit...
+
+ if (g_bDoEmptyExit)
+ {
+ DEC_TIMER(g_timerEmptyExit, g_timeDelta);
+ if (g_timerEmptyExit == 0)
+ {
+ g_bNoExitConfirm = TRUE;
+ PostMessage(WM_CLOSE);
+ }
+ }
+
+
+ // Update the server manager...
+
+ UpdateServerMgr(g_timeDelta);
+ if (!IsRunning()) return;
+
+
+ // Update the game spy manager...
+
+ UpdateGameSpyMgr(g_timeDelta);
+
+
+ // Update the server registration...
+
+ UpdateServerRegistration(g_timeDelta);
+ }
+}
+
+void CGameServDlg::UpdateTimers()
+{
+ DWORD timeCur;
+
+ if(!IsRunning())
+ return;
+
+ timeCur = timeGetTime();
+
+ // Update the server time...
+
+ m_timeServerRunning = timeCur - m_timeServerStart;
+ if ((m_timeServerLast / 1000) != (m_timeServerRunning / 1000))
+ {
+ SetDlgItemText(IDC_SERVER_TIME, TimeToString(m_timeServerRunning));
+ m_timeServerLast = m_timeServerRunning;
+ }
+
+
+ // Update the game/level time...
+
+ m_timeLevelRunning = timeCur - m_timeLevelStart;
+ if ((m_timeLevelLast / 1000) != (m_timeLevelRunning / 1000))
+ {
+ SetDlgItemText(IDC_GAME_TIME, TimeToString(m_timeLevelRunning));
+ m_timeLevelLast = m_timeLevelRunning;
+ }
+
+
+ // Remove any update messages in the queue...
+
+ RemoveMessage(WM_TIMER, 500);
+}
+
+
+void CGameServDlg::OnQuit()
+{
+ PostMessage(WM_COMMAND, IDCANCEL);
+}
+
+void CGameServDlg::OnServer()
+{
+ PostMessage(WM_COMMAND, IDCANCEL);
+}
+
+BOOL CGameServDlg::UpdateServerRegistration(DWORD timeDelta)
+{
+ // Sanity checks...
+
+ if (!m_pServerMgr) return(FALSE);
+ if (!g_ServerInfo.m_bRegisterServer) return(FALSE);
+ if (g_ServerInfo.m_sAddress[0] == '\0') return(FALSE);
+
+
+ // Check if it's really time to update...
+
+ static DWORD timerUpdate = 7000;
+
+ DEC_TIMER(timerUpdate, timeDelta);
+ if (timerUpdate != 0) return(FALSE);
+ else timerUpdate = s_timerWebRegUpdate * 1000;
+
+
+ // Build the info string...
+
+ CString sInfo;
+
+ sInfo.Format("game=%s&name=%s&ip=%s&players=%i&version=%s", g_sWebGameName, g_ServerInfo.m_sName, g_sFullTcpIpAddress, m_pServerMgr->GetNumClients(), g_sWebGameVer);
+
+
+ // Send the server info the web page...
+
+ SendWebInfo(sInfo, FALSE);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL CGameServDlg::UpdateGameSpyMgr(DWORD timeDelta)
+{
+ // Sanity checks...
+
+ if (!m_pServerMgr) return(FALSE);
+ if (!g_ServerInfo.m_bUseGameSpy) return(FALSE);
+
+
+ // Update the GameSpy manager...
+
+ m_GameSpyMgr.Update();
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL CGameServDlg::UnregisterServer()
+{
+ // Sanity checks...
+
+ if (!g_ServerInfo.m_bRegisterServer) return(FALSE);
+ if (g_ServerInfo.m_sAddress[0] == '\0') return(FALSE);
+
+
+ // Build the info string...
+
+ CString sInfo;
+
+ sInfo.Format("game=%s&name=%s&ip=%s&players=-1&version=%s", g_sWebGameName, g_ServerInfo.m_sName, g_sFullTcpIpAddress, g_sWebGameVer);
+
+
+ // Send the server info the web page...
+
+ SendWebInfo(sInfo, FALSE);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+void CGameServDlg::OnShellMessage(char* pMsg)
+{
+ // Sanity checks...
+
+ if (!pMsg) return;
+
+
+ // Figure out what type of message this if...
+
+ char sTemp[128];
+
+ if (!Sparam_Get(sTemp, pMsg, NST_GENERICMESSAGE))
+ {
+ return;
+ }
+
+ switch (atoi(sTemp))
+ {
+ case NGM_STANDARDUPDATE: OnStandardUpdate(pMsg); break;
+ case NGM_LEVELCHANGING: OnLevelChanging(pMsg); break;
+ case NGM_LEVELCHANGED: OnLevelChangeUpdate(pMsg); break;
+ case NGM_LEVELCHANGESTOP: OnLevelChangeStop(); break;
+ case NGM_CONSOLEMSG: OnConsoleMessageUpdate(pMsg); break;
+ }
+}
+
+
+int ClientIDToIndex(ServerInterface *pInterface, DWORD id)
+{
+ int i, count;
+ ClientInfo info;
+
+ count = pInterface->GetNumClients();
+ for(i=0; i < count; i++)
+ {
+ pInterface->GetClientInfo(i, &info);
+ if(info.m_ClientID == id)
+ return i;
+ }
+ return -1;
+}
+
+
+void CGameServDlg::OnStandardUpdate(char* pMsg)
+{
+ // Update the level info...
+
+ char sTemp[128];
+
+ if (Sparam_Get(sTemp, pMsg, NST_CURLEVEL))
+ {
+ SetDlgItemText(IDC_GAME_CURLEVEL, sTemp);
+ }
+
+ if (Sparam_Get(sTemp, pMsg, NST_NEXTLEVEL))
+ {
+ SetDlgItemText(IDC_GAME_NEXTLEVEL, sTemp);
+ }
+
+
+ // Get the current player selection info...
+
+ CString sCurSel;
+ CString sCurSelName;
+ int nCurSel = m_lbPlayers.GetCurSel();
+
+ if (nCurSel != LB_ERR)
+ {
+ m_lbPlayers.GetText(nCurSel, sCurSel);
+
+ int i = 0;
+
+ while (sCurSel[i] >= 32)
+ {
+ sCurSelName += sCurSel[i];
+ i++;
+ }
+ }
+
+
+ // Update the player info...
+
+ m_lbPlayers.ResetContent();
+
+ int count = 0;
+ int cPlayers = 0;
+ int nNewSel = nCurSel;
+
+ if (Sparam_Get(sTemp, pMsg, NST_PLRCOUNT))
+ {
+ count = atoi(sTemp);
+ }
+
+ for (int i = 1; i <= count; i++)
+ {
+ char sBase[32];
+ char sName[64];
+
+ int j = i-1;
+
+ wsprintf(sBase, "%s%i", NST_PLRNAME_BASE, i);
+
+ if (Sparam_Get(sName, pMsg, sBase))
+ {
+ strcpy(m_aPis[j].sName, sName);
+
+ wsprintf(sBase, "%s%i", NST_PLRFRAG_BASE, i);
+
+ if (Sparam_Get(sTemp, pMsg, sBase))
+ {
+ m_aPis[j].nFrags = atoi(sTemp);
+
+ wsprintf(sBase, "%s%i", NST_PLRID_BASE, i);
+
+ if (Sparam_Get(sTemp, pMsg, sBase))
+ {
+ m_aPis[j].dwID = atoi(sTemp);
+ }
+ else
+ {
+ m_aPis[j].dwID = 0;
+ }
+ }
+ }
+
+ int clientIndex = ClientIDToIndex(m_pServerMgr, m_aPis[j].dwID);
+ m_aPis[j].dwPing = 0;
+ if(clientIndex != -1)
+ {
+ ClientInfo info;
+
+ if(m_pServerMgr->GetClientInfo(clientIndex, &info))
+ {
+ m_aPis[j].dwPing = (DWORD)(info.m_Ping * 1000.0f);
+ }
+ }
+
+ cPlayers++;
+ }
+
+
+ // Sort the players...
+
+ PLAYERINFO TempPi;
+
+ for (i = 0; i < count - 1; i++)
+ {
+ for (int j = i+1; j < count; j++)
+ {
+ BOOL bSwap = FALSE;
+
+ if (m_aPis[i].nFrags < m_aPis[j].nFrags) bSwap = TRUE;
+
+ if (m_aPis[i].nFrags == m_aPis[j].nFrags)
+ {
+ if (strcmp(m_aPis[i].sName, m_aPis[j].sName) > 0) bSwap = TRUE;
+ }
+
+ if (bSwap)
+ {
+ memcpy(&TempPi, &m_aPis[i], sizeof(PLAYERINFO));
+ memcpy(&m_aPis[i], &m_aPis[j], sizeof(PLAYERINFO));
+ memcpy(&m_aPis[j], &TempPi, sizeof(PLAYERINFO));
+ }
+ }
+ }
+
+
+ // Add the players to the list box...
+
+ nNewSel = LB_ERR;
+
+ for (i = 0; i < count; i++)
+ {
+ CString sPlayer;
+ sPlayer.Format("(%d)\t%s\t%i", m_aPis[i].dwPing, m_aPis[i].sName, m_aPis[i].nFrags);
+ int nIndex = m_lbPlayers.AddString(sPlayer);
+
+ if (nIndex != LB_ERR)
+ {
+ m_lbPlayers.SetItemData(nIndex, m_aPis[i].dwID);
+
+ if (!sCurSelName.IsEmpty() && strcmp(m_aPis[i].sName, sCurSelName) == 0) nNewSel = nIndex;
+ }
+ }
+
+
+ // Reselect the selected player if necessary...
+
+ if (nNewSel != LB_ERR)
+ {
+ m_lbPlayers.SetCurSel(nNewSel);
+ }
+
+ CWnd* pWnd = GetDlgItem(IDC_PLAYERS_BOOT);
+ if (pWnd)
+ {
+ pWnd->EnableWindow(nNewSel != LB_ERR);
+ }
+
+
+ // Check for empty exit...
+
+ if (g_bEmptyExit)
+ {
+ if (m_cPlayers > 0 && cPlayers == 0)
+ {
+ WriteConsoleString(IDS_CONSOLE_LASTPLAYERLEFT);
+ g_bDoEmptyExit = TRUE;
+ g_timerEmptyExit = g_nEmptyExitDelay * 1000;
+ }
+ else
+ {
+ if (cPlayers >= 1) g_bDoEmptyExit = FALSE;
+ }
+ }
+
+
+ // Set the number of players...
+
+ m_cPlayers = cPlayers;
+
+ SetDlgItemInt(IDC_GAME_PLAYERS, cPlayers);
+}
+
+void CGameServDlg::OnLevelChanging(char* pMsg)
+{
+ // Flag the the level is changing...
+ m_bLevelChanging = TRUE;
+ EnterCriticalSection(&m_CS);
+}
+
+void CGameServDlg::OnLevelChangeUpdate(char* pMsg)
+{
+ OnLevelChangeStop();
+
+ // Update the level info...
+
+ char sTemp[128];
+
+ if (Sparam_Get(sTemp, pMsg, NST_CURLEVEL))
+ {
+ SetDlgItemText(IDC_GAME_CURLEVEL, sTemp);
+ m_sCurLevel = sTemp;
+ }
+
+ if (Sparam_Get(sTemp, pMsg, NST_NEXTLEVEL))
+ {
+ SetDlgItemText(IDC_GAME_NEXTLEVEL, sTemp);
+ }
+
+
+ // Reset the level timer...
+
+ m_timeLevelStart = timeGetTime();
+}
+
+void CGameServDlg::OnLevelChangeStop()
+{
+ // Flag the level is done changing and is now changed...
+ m_bLevelChanging = FALSE;
+ LeaveCriticalSection(&m_CS);
+}
+
+void CGameServDlg::OnConsoleMessageUpdate(char* pMsg)
+{
+ char sTemp[128];
+
+ if (Sparam_Get(sTemp, pMsg, NST_CONSOLEMSG))
+ {
+ WriteConsoleString(sTemp);
+ }
+}
+
+void CGameServDlg::OnConsoleOutput(char* pMsg)
+{
+ WriteConsoleString(pMsg);
+}
+
+void CGameServDlg::OnConsoleSend()
+{
+ if (!m_pServerMgr) return;
+
+ char sCmd[128];
+ sCmd[0] = '\0';
+ if (GetDlgItemText(IDC_CONSOLE_COMMAND, sCmd, 120) == 0) return;
+
+ WriteConsoleString(sCmd);
+ SetDlgItemText(IDC_CONSOLE_COMMAND, "");
+
+ m_pServerMgr->RunConsoleString(sCmd);
+
+ UpdateConsoleVars();
+}
+
+void CGameServDlg::OnConsoleClear()
+{
+ SetDlgItemText(IDC_CONSOLE_WINDOW, "");
+}
+
+BOOL CGameServDlg::DestroyWindow()
+{
+ StopServer();
+ Clear();
+ return(CDialog::DestroyWindow());
+}
+
+void CGameServDlg::OnOutOfMemory()
+{
+ AfxMessageBox(IDS_ERROR_MEMORY);
+ g_bNoExitConfirm = TRUE;
+ SendMessage(WM_COMMAND, IDCANCEL);
+ exit(0);
+}
+
+void CGameServDlg::OnCommandsNextLevel()
+{
+ if (m_pServerMgr)
+ {
+ WriteConsoleString(IDS_NEXTLEVEL);
+ m_pServerMgr->SendToServerShell("NEXTLEVEL");
+ }
+}
+
+void CGameServDlg::OnPlayersBoot()
+{
+ int nCurSel = m_lbPlayers.GetCurSel();
+ if (nCurSel == LB_ERR) return;
+
+ DWORD dwID = m_lbPlayers.GetItemData(nCurSel);
+
+ m_pServerMgr->BootClient(dwID);
+}
+
+void CGameServDlg::OnSelchangePlayersList()
+{
+ int nCurSel = m_lbPlayers.GetCurSel();
+
+ CWnd* pWnd = GetDlgItem(IDC_PLAYERS_BOOT);
+ if (pWnd)
+ {
+ pWnd->EnableWindow(nCurSel != LB_ERR);
+ }
+}
+
+DWORD WINAPI ThreadUpdate(LPVOID lpParameter)
+{
+ // Sanity checks...
+
+ if (!lpParameter) return(0);
+
+
+ // Call the update until we are done...
+
+ CGameServDlg* pDlg = (CGameServDlg*)lpParameter;
+ HWND hWnd = pDlg->GetSafeHwnd();
+
+ while (pDlg->IsRunning())
+ {
+ DWORD timeNow = timeGetTime();
+
+ if (timeNow - g_timeCur >= 8 && !pDlg->IsLevelChanging())
+ {
+
+#if USE_POSTMSG
+ pDlg->RemoveMessage(WM_TIMER, 500);
+ pDlg->PostMessage(WM_TIMER);
+ g_dwPosted++;
+#else
+ EnterCriticalSection(pDlg->GetCS());
+ pDlg->OnUpdate();
+ LeaveCriticalSection(pDlg->GetCS());
+#endif
+
+ }
+
+ Sleep(9);
+ }
+
+
+ // All done...
+
+ s_bThreadDone = TRUE;
+ SS_Trace("Thread is exiting...\n");
+ return(TRUE);
+}
+
+void CGameServDlg::OnCancel()
+{
+ if (g_bNoExitConfirm)
+ {
+ StopServer();
+ CDialog::OnCancel();
+ return;
+ }
+
+ CString str, title;
+
+ str.LoadString(IDS_CHECKEXIT);
+
+#ifdef _ADDON
+ title.LoadString(IDS_APPNAME_AO);
+#else
+ title.LoadString(IDS_APPNAME);
+#endif
+
+ if (MessageBox(str, title, MB_YESNO | MB_ICONQUESTION) == IDYES)
+ {
+ StopServer();
+ CDialog::OnCancel();
+ }
+}
+
+void CGameServDlg::OnDestroy()
+{
+ StopServer();
+ CDialog::OnDestroy();
+}
+
+void CGameServDlg::RemoveMessage(int nMsg, int nMax)
+{
+ MSG msg;
+
+ for (int i = 0; i < nMax; i++)
+ {
+ if (!PeekMessage(&msg, GetSafeHwnd(), nMsg, nMsg, PM_REMOVE))
+ {
+ return;
+ }
+
+ g_dwRemoved++;
+ }
+}
+
+PLAYERINFO* CGameServDlg::GetFirstPlayerInfo()
+{
+ if (m_cPlayers <= 0) return(NULL);
+
+ m_iPlayer = -1;
+
+ return(GetNextPlayerInfo());
+}
+
+PLAYERINFO* CGameServDlg::GetNextPlayerInfo()
+{
+ m_iPlayer++;
+ if (m_iPlayer >= m_cPlayers) return(NULL);
+
+ return(&m_aPis[m_iPlayer]);
+}
+
+void CGameServDlg::OnCommandsOptions()
+{
+ NetStart_DoOptionsDialog(GetSafeHwnd(), m_pServerMgr, &g_ServerOptions);
+}
+
+void CGameServDlg::OnProcessNetPacket(char* sData, DWORD nLen, BYTE senderAddr[4], DWORD senderPort)
+{
+ char sAddr[128];
+
+ if (g_ServerInfo.m_bUseGameSpy)
+ {
+ if(nLen > 0 && sData[0] == '\\')
+ {
+ sprintf(sAddr, "%d.%d.%d.%d", senderAddr[0], senderAddr[1], senderAddr[2], senderAddr[3]);
+ m_GameSpyMgr.OnQuery(sAddr, senderPort, sData, nLen);
+ }
+ }
+}
+
+void CGameServDlg::UpdateConsoleVars()
+{
+ HCONSOLEVAR hVar = NULL;
+ DRESULT dr = m_pServerMgr->GetConsoleVar("SpyGameType", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ char sTemp[64] = { "" };
+ dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
+ if (dr == LT_OK && sTemp[0] != '\0')
+ {
+ m_sGameSpyGameType = sTemp;
+ }
+ }
+
+ hVar = NULL;
+ dr = m_pServerMgr->GetConsoleVar("SpyGameMode", &hVar, NULL);
+ if (dr == LT_OK && hVar)
+ {
+ char sTemp[64] = { "" };
+ dr = m_pServerMgr->GetVarValueString(hVar, sTemp, 64);
+ if (dr == LT_OK && sTemp[0] != '\0')
+ {
+ m_sGameSpyGameMode = sTemp;
+ }
+ }
+}
diff --git a/Blood2Serv/GameServDlg.h b/Blood2Serv/GameServDlg.h
new file mode 100644
index 0000000..da1337d
--- /dev/null
+++ b/Blood2Serv/GameServDlg.h
@@ -0,0 +1,179 @@
+#if !defined(AFX_GAMESERVDLG_H__CB06D3C1_2B86_11D2_860A_00609719A842__INCLUDED_)
+#define AFX_GAMESERVDLG_H__CB06D3C1_2B86_11D2_860A_00609719A842__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// GameServDlg.h : header file
+//
+
+
+// Includes...
+
+#include "ServerUtils.h"
+#include "MyGameSpyMgr.h"
+#include "NetDefs.h"
+
+
+// Structures...
+
+typedef struct PlayerInfo_t
+{
+ char sName[64];
+ int nFrags;
+ DWORD dwID;
+ DWORD dwPing;
+
+} PLAYERINFO;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CGameServDlg dialog
+
+class CGameServDlg;
+
+class CGameServSendHandler : public CGameSpySender
+{
+public:
+ CGameServSendHandler() { m_pDlg = NULL; }
+
+ void SetDlg(CGameServDlg *pDlg) {m_pDlg = pDlg;}
+ void SendTo(const void *pData, unsigned long len, const char *sAddr, unsigned long port);
+
+protected:
+ CGameServDlg* m_pDlg;
+};
+
+class CGameServDlg : public CDialog
+{
+// Construction
+public:
+ CGameServDlg(CWnd* pParent = NULL); // standard constructor
+ ~CGameServDlg() { Term(); }
+
+// Dialog Data
+ //{{AFX_DATA(CGameServDlg)
+ enum { IDD = IDD_GAMESERVER };
+ CListBox m_lbPlayers;
+ CListBox m_lbLevels;
+ CEdit m_edConsole;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CGameServDlg)
+ public:
+ virtual BOOL DestroyWindow();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CGameServDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
+ afx_msg void OnClose();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnQuit();
+ afx_msg void OnServer();
+ afx_msg void OnConsoleSend();
+ afx_msg void OnConsoleClear();
+ afx_msg void OnCommandsNextLevel();
+ afx_msg void OnPlayersBoot();
+ afx_msg void OnSelchangePlayersList();
+ virtual void OnCancel();
+ afx_msg void OnDestroy();
+ afx_msg void OnCommandsOptions();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+
+ // Member functions...
+
+public:
+ BOOL Init();
+ void Term();
+ void Clear();
+
+ CString GetCurLevel() { return(m_sCurLevel); }
+ int GetNumPlayers() { return(m_cPlayers); }
+ PLAYERINFO* GetFirstPlayerInfo();
+ PLAYERINFO* GetNextPlayerInfo();
+ CString GetGameSpyGameMode() { return(m_sGameSpyGameMode); }
+ CString GetGameSpyGameType() { return(m_sGameSpyGameType); }
+
+ BOOL StartServer();
+ BOOL StopServer();
+ BOOL IsRunning() { return(m_bRunning); }
+ BOOL IsLevelChanging() { return(m_bLevelChanging); }
+
+ void UpdateServerMgr(DWORD timeDelta);
+ BOOL UpdateServerRegistration(DWORD timeDelta);
+ BOOL UpdateGameSpyMgr(DWORD timeDelta);
+ void UpdateConsoleVars();
+
+ BOOL UnregisterServer();
+
+ void RemoveMessage(int nMsg, int nMax);
+
+ void WriteConsoleString(LPCTSTR pMsg, ...);
+ void WriteConsoleString(int nStringID);
+ void WriteServerError();
+
+ void OnUpdate();
+ void UpdateTimers();
+ void OnShellMessage(char* pMsg);
+ void OnConsoleOutput(char* pMsg);
+ void OnOutOfMemory();
+ void OnProcessNetPacket(char* sData, DWORD nLen, BYTE senderAddr[4], DWORD senderPort);
+
+ ServerInterface* GetServerMgr() {return m_pServerMgr;}
+ void SetConfigFilename(char *pName) {m_pConfigFilename = pName;}
+ CRITICAL_SECTION* GetCS() {return &m_CS;}
+
+private:
+ void OnStandardUpdate(char* pMsg);
+ void OnLevelChanging(char* pMsg);
+ void OnLevelChangeUpdate(char* pMsg);
+ void OnLevelChangeStop();
+ void OnConsoleMessageUpdate(char* pMsg);
+
+
+ // Member variables...
+
+private:
+ CRITICAL_SECTION m_CS; // So we don't switch levels and update at the same time.
+ BOOL m_bCSInitted;
+
+ char *m_pConfigFilename;
+ CGameServSendHandler m_SendHandler;
+ ServerInterface* m_pServerMgr;
+ BOOL m_bRunning;
+ BOOL m_bLevelChanging;
+ DWORD m_timeServerStart;
+ DWORD m_timeServerRunning;
+ DWORD m_timeServerLast;
+ DWORD m_timeLevelStart;
+ DWORD m_timeLevelRunning;
+ DWORD m_timeLevelLast;
+ int m_iPlayer;
+ int m_cPlayers;
+ int m_nCurLevel;
+ CString m_sCurLevel;
+ HANDLE m_hThread;
+ DWORD m_dwThreadID;
+ CMyGameSpyMgr m_GameSpyMgr;
+ CString m_sGameSpyGameMode;
+ CString m_sGameSpyGameType;
+ PLAYERINFO m_aPis[MAX_MULTI_PLAYERS + 2];
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_GAMESERVDLG_H__CB06D3C1_2B86_11D2_860A_00609719A842__INCLUDED_)
diff --git a/Blood2Serv/MyGameSpyMgr.cpp b/Blood2Serv/MyGameSpyMgr.cpp
new file mode 100644
index 0000000..6d1df81
--- /dev/null
+++ b/Blood2Serv/MyGameSpyMgr.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+;
+; MODULE: MYGAMESPYMGR (.CPP)
+;
+; PURPOSE: Derived Game Spy Manager for this game server
+;
+; HISTORY: 09/21/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions, Inc.
+;
+****************************************************************************/
+
+
+// Includes...
+
+#include "StdAfx.h"
+#include "Resource.h"
+#include "MyGameSpyMgr.h"
+#include "GameServDlg.h"
+#include "NetStart.h"
+
+
+// Externs...
+
+extern ServerInfo g_ServerInfo;
+extern ServerOptions g_ServerOptions;
+extern NetGame g_NetGame;
+extern CGameServDlg* g_pDialog;
+
+
+// Functions...
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: CMyGameSpyMgr::OnInfoQuery
+//
+// PURPOSE: Handles the "info" query
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CMyGameSpyMgr::OnInfoQuery()
+{
+ // Sanity checks...
+
+ if (!g_pDialog) return(FALSE);
+
+
+ // Prepare the level name by stripping out the prefixes...
+
+ char sLevel[128];
+ char sTemp[128];
+ strcpy(sLevel, g_pDialog->GetCurLevel());
+ strcpy(sTemp, g_pDialog->GetCurLevel());
+
+ int nLen = strlen(sTemp);
+
+ if (nLen > 2)
+ {
+ int i = nLen - 1;
+
+ while (i > 0 && sTemp[i] != '\\')
+ {
+ i--;
+ }
+
+ if (i < nLen - 1)
+ {
+ if (sTemp[i] == '\\') i++;
+ strcpy(sLevel, &sTemp[i]);
+ }
+ }
+
+
+ // Send the info...
+
+ SendResponseInfo("hostname", g_ServerInfo.m_sName);
+ SendResponseInfo("hostport", GetGamePort());
+ SendResponseInfo("mapname", sLevel);
+ SendResponseInfo("gametype", g_pDialog->GetGameSpyGameType());
+ SendResponseInfo("numplayers", g_pDialog->GetNumPlayers());
+ SendResponseInfo("maxplayers", g_ServerInfo.m_dwMaxPlayers);
+ SendResponseInfo("gamemode", g_pDialog->GetGameSpyGameMode());
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: CMyGameSpyMgr::OnRulesQuery
+//
+// PURPOSE: Handles the "rules" query
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CMyGameSpyMgr::OnRulesQuery()
+{
+ // Send the rules...
+
+ if (g_NetGame.m_byEnd == NGE_TIME || g_NetGame.m_byEnd == NGE_FRAGSANDTIME)
+ {
+ SendResponseInfo("timelimit", g_NetGame.m_dwEndTime);
+ }
+ else
+ {
+ SendResponseInfo("timelimit", 0);
+ }
+
+ if (g_NetGame.m_byEnd == NGE_FRAGS || g_NetGame.m_byEnd == NGE_FRAGSANDTIME)
+ {
+ SendResponseInfo("timelimit", g_NetGame.m_dwEndFrags);
+ }
+ else
+ {
+ SendResponseInfo("timelimit", 0);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: CMyGameSpyMgr::OnPlayersQuery
+//
+// PURPOSE: Handles the "players" query
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CMyGameSpyMgr::OnPlayersQuery()
+{
+ // Sanity checks...
+
+ if (!g_pDialog) return(FALSE);
+
+
+ // Send the info for each player...
+
+ int count = 0;
+
+ PLAYERINFO* pPi = g_pDialog->GetFirstPlayerInfo();
+
+ while (pPi)
+ {
+ char sPlayer[32];
+ sprintf(sPlayer, "player_%i", count);
+ SendResponseInfo(sPlayer, pPi->sName);
+
+ char sFrags[32];
+ sprintf(sFrags, "frags_%i", count);
+ SendResponseInfo(sFrags, pPi->nFrags);
+
+ char sPing[32];
+ sprintf(sPing, "ping_%i", count);
+ SendResponseInfo(sPing, pPi->dwPing);
+
+ count++;
+ pPi = g_pDialog->GetNextPlayerInfo();
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
diff --git a/Blood2Serv/MyGameSpyMgr.h b/Blood2Serv/MyGameSpyMgr.h
new file mode 100644
index 0000000..87f0b73
--- /dev/null
+++ b/Blood2Serv/MyGameSpyMgr.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+;
+; MODULE: MYGAMESPYMGR (.H)
+;
+; PURPOSE: Derived Game Spy Manager for this game server
+;
+; HISTORY: 09/21/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions, Inc.
+;
+****************************************************************************/
+
+
+#ifndef _MYGAMESPYMGR_H_
+#define _MYGAMESPYMGR_H_
+
+
+// Includes...
+
+#include "GameSpyMgr.h"
+
+
+// Classes...
+
+class CMyGameSpyMgr : public CGameSpyMgr
+{
+ // Member functions...
+
+public:
+ virtual BOOL OnInfoQuery();
+ virtual BOOL OnRulesQuery();
+ virtual BOOL OnPlayersQuery();
+};
+
+
+// EOF...
+
+#endif
+
diff --git a/Blood2Serv/NetDefs.h b/Blood2Serv/NetDefs.h
new file mode 100644
index 0000000..c0000c0
--- /dev/null
+++ b/Blood2Serv/NetDefs.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+;
+; MODULE: NetDefs (.H)
+;
+; PURPOSE: Network game definitions
+;
+; HISTORY: 07/09/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+#ifndef _NETDEFS_H_
+#define _NETDEFS_H_
+
+
+// Includes...
+
+#include "basetypes_de.h"
+
+
+// Defines...
+
+#define NGT_SINGLE 0 // NGT: net game type
+#define NGT_DEATHMATCH 1
+#define NGT_CAPTUREFLAG 2
+#define NGT_COOPERATIVE 3
+#define NGT_TEAMS 4
+#define NGT_SOCCER 5
+#define NGT_TOETAG 6
+
+#define NML_NAME 128 // NML: net max len
+#define NML_HOST 128
+#define NML_LEVEL 128
+#define NML_PLAYERS 128
+#define NML_GAMES 128
+
+#define NST_GAMENAME "NAME" // NST: net string token
+#define NST_GAMEHOST "HOST"
+#define NST_GAMETYPE "TYPE"
+#define NST_GAMELEVEL "LEVL"
+#define NST_GAMETIME "TIME"
+#define NST_PLRCOUNT "PLRS"
+#define NST_PLRNAME_BASE "PLRN"
+#define NST_PLRFRAG_BASE "PLRF"
+#define NST_PLRID_BASE "PLRI"
+#define NST_CURLEVEL "CLEV"
+#define NST_NEXTLEVEL "NLEV"
+#define NST_GENERICMESSAGE "GMSG"
+#define NST_CONSOLEMESSAGE "CMSG"
+
+#define NGE_FRAGS 1 // NGE: net game end
+#define NGE_TIME 2
+#define NGE_FRAGSANDTIME 3
+#define NGE_NEVER 4
+
+#define NGM_STANDARDUPDATE 0 // NGM: net generic message
+#define NGM_LEVELCHANGED 1
+#define NGM_CONSOLEMSG 2
+#define NGM_LEVELCHANGING 3
+#define NGM_LEVELCHANGESTOP 4
+
+#define LEVEL_NONE 0
+#define LEVEL_HALF 1
+#define LEVEL_NORMAL 2
+#define LEVEL_DOUBLE 3
+#define LEVEL_INSANE 4
+
+#define HEAL_NONE 0
+#define HEAL_REALLYSLOW 1
+#define HEAL_SLOW 2
+#define HEAL_NORMAL 3
+#define HEAL_FAST 4
+#define HEAL_REALLYFAST 5
+
+#define TEAM_AUTO 0
+#define TEAM_1 1
+#define TEAM_2 2
+
+#define MAX_PLAYER_NAME 32
+#define MAX_CONFIG_NAME 64
+#define MAX_GAME_LEVELS 50
+
+#define MAX_MULTI_PLAYERS 128
+#define MAX_MULTI_PLAYERS_DISPLAY 16
+
+#define SOCBALL_SKIN_SOCCER 0
+#define SOCBALL_SKIN_ZOMBIE 1
+
+
+// Structures...
+
+typedef struct NetPlayer_t
+{
+ char m_sName[MAX_PLAYER_NAME];
+ char m_sConfig[MAX_CONFIG_NAME];
+ DDWORD m_dwTeam;
+ DDWORD m_dwLatency;
+
+} NetPlayer;
+
+typedef struct NetGame_t
+{
+ DBYTE m_byType;
+ DBYTE m_byEnd;
+ DDWORD m_dwEndFrags;
+ DDWORD m_dwEndTime;
+ DBYTE m_byNumLevels;
+ char m_sLevels[MAX_GAME_LEVELS][NML_LEVEL];
+ int m_nAmmoLevel;
+ int m_nAmmoRespawn;
+ int m_nArmorLevel;
+ int m_nArmorRespawn;
+ int m_nHealthLevel;
+ int m_nHealthRespawn;
+ int m_nPowerupsLevel;
+ int m_nPowerupsRespawn;
+ int m_nHealingRate;
+ int m_nFlagValue;
+ int m_nGoalValue;
+ DBOOL m_bFallDamage;
+ DBOOL m_bFriendlyFire;
+ DBOOL m_bNegTeamFrags;
+ DBOOL m_bOnlyFlagScores;
+ DBOOL m_bOnlyGoalScores;
+ DBOOL m_bUseTeamSize;
+ int m_nSocBallSkin;
+
+} NetGame;
+
+typedef struct ServerOptions_t
+{
+ DFLOAT m_fRunSpeed;
+ DFLOAT m_fMissileSpeed;
+ DFLOAT m_fWorldTimeSpeed;
+ char m_sWorldNightColor[32];
+
+} ServerOptions;
+
+
+// EOF...
+
+#endif
diff --git a/Blood2Serv/NetStart.cpp b/Blood2Serv/NetStart.cpp
new file mode 100644
index 0000000..eafcca6
--- /dev/null
+++ b/Blood2Serv/NetStart.cpp
@@ -0,0 +1,3228 @@
+/****************************************************************************
+;
+; MODULE: NetStart (.CPP)
+;
+; PURPOSE: Network game start/join/host dialog code
+;
+; HISTORY: 06/28/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+// Includes...
+
+#include "StdAfx.h"
+#include "NetStart.h"
+#include "CoolServ.h"
+#include "Resource.h"
+#include "ServerUtils.h"
+#include "Direct.h"
+#include "io.h"
+
+
+// Guids...
+
+#ifdef _ADDON
+
+DGUID GAMEGUID = { /* Add-On */
+ 0xc13e628, 0x418c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x18, 0xa9, 0x42
+};
+
+#else
+
+DGUID GAMEGUID = { /* 0C13E629-419C-11D2-860A-00609719A842 */
+ 0xc13e629, 0x419c, 0x11d2, 0x86, 0xa, 0x0, 0x60, 0x97, 0x19, 0xa8, 0x42
+};
+
+#endif
+
+
+// Defines...
+
+#define DLG_NEXT 1
+#define DLG_CANCEL 2
+#define DLG_BACK 3
+#define DLG_ERROR 4
+
+#define RETAIL_LEVEL 0
+#define CUSTOM_LEVEL 1
+#define ADDON_LEVEL 2
+
+#define HOURS_PER_SEC 0.00027f
+
+
+// Statics...
+
+static ServerInterface* s_pServerMgr = NULL;
+static ServerInfo* s_pServerInfo = NULL;
+static ServerOptions* s_pServerOptions = NULL;
+static NetGame* s_pNetGame = NULL;
+static HWND s_hMainWnd = NULL;
+static HICON s_hIcon = NULL;
+static HINSTANCE s_hInst = NULL;
+
+static char s_sServerName[256] = { "" };
+static char s_sServiceName[256] = { "" };
+
+static int s_nGameType = NGT_DEATHMATCH;
+static int s_nEndType = NGE_FRAGS;
+static int s_nEndFrags = 25;
+static int s_nEndTime = 10;
+static int s_nNetService = 0;
+static int s_nMaxPlayers = MAX_MULTI_PLAYERS_DISPLAY;
+static int s_nPort = 0;
+static int s_nAmmoLevel = LEVEL_NORMAL;
+static int s_nAmmoRespawn = 15;
+static int s_nArmorLevel = LEVEL_NORMAL;
+static int s_nArmorRespawn = 45;
+static int s_nHealthLevel = LEVEL_NORMAL;
+static int s_nHealthRespawn = 30;
+static int s_nPowerupsLevel = LEVEL_NORMAL;
+static int s_nPowerupsRespawn = 60;
+static int s_nHealingRate = 0;
+static int s_nTeam = 0;
+static int s_nErrorString = IDS_NETERR_GENERIC;
+static int s_nFlagValue = 5;
+static int s_nGoalValue = 5;
+static int s_nSocBallSkin = 0;
+
+static BOOL s_bFallDamage = FALSE;
+static BOOL s_bUpdateInfo = TRUE;
+static BOOL s_bServerReg = TRUE;
+static BOOL s_bUseGameSpy = TRUE;
+static BOOL s_bDashGoInfo = FALSE;
+static BOOL s_bIsTcpIp = FALSE;
+static BOOL s_bFriendlyFire = TRUE;
+static BOOL s_bNegTeamFrags = TRUE;
+static BOOL s_bOnlyFlagScores = FALSE;
+static BOOL s_bUseTeamSize = FALSE;
+static BOOL s_bOnlyGoalScores = FALSE;
+
+static CStringList s_collLevels;
+static CStringList s_collRezFiles;
+
+
+// Macros...
+
+#define RM_GET_FLOAT(s, f, d) { char sBuf[64] = {""}; UINT32 uSize = 62; rm.Get(s, sBuf, uSize, ""); if (strlen(sBuf) > 0) f = (float)atof(sBuf); else f = d; }
+#define RM_SET_FLOAT(s, f) { char sBuf[64]; sprintf(sBuf, "%f", f); rm.Set(s, sBuf); }
+
+
+// Prototypes...
+
+BOOL NetStart_HandleDefaultDialogCommands(HWND hDlg, WPARAM wParam);
+void NetStart_DisplayError();
+BOOL NetStart_GetWorldNightColor(HWND hParenWnd);
+
+BOOL NetStart_FillServiceList(HWND hList);
+BOOL NetStart_SelectCurrentService(HWND hList);
+
+BOOL NetStart_FillGameInfo(HWND hDlg);
+BOOL NetStart_FillLevelList(HWND hList, char* sDir, int nData, BOOL bClearList = TRUE);
+BOOL NetStart_FillGameLevels(HWND hDlg);
+BOOL NetStart_FillGameEnd(HWND hDlg);
+BOOL NetStart_FillGameItems(HWND hDlg);
+BOOL NetStart_FillGameDamage(HWND hDlg);
+BOOL NetStart_FillGameType(HWND hDlg);
+BOOL NetStart_FillOptions(HWND hDlg);
+BOOL NetStart_FillTeamOptions(HWND hDlg);
+BOOL NetStart_FillCtfOptions(HWND hDlg);
+BOOL NetStart_FillSoccerOptions(HWND hDlg);
+
+BOOL NetStart_InitGameType(HWND hDlg);
+BOOL NetStart_InitGameItems(HWND hDlg);
+BOOL NetStart_InitGameDamage(HWND hDlg);
+BOOL NetStart_InitOptions(HWND hDlg);
+BOOL NetStart_InitTeamOptions(HWND hDlg);
+BOOL NetStart_InitCtfOptions(HWND hDlg);
+BOOL NetStart_InitSoccerOptions(HWND hDlg);
+
+BOOL NetStart_SetEndGameInfo(HWND hDlg);
+
+BOOL NetStart_IsOkToDisplayLevel(char* sLevel);
+
+BOOL CALLBACK NetDlg_Welcome(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_Services(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_Game(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_Options(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_TeamOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_CtfOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_SoccerOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_GameEnd(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_GameLevels(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_GameItems(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_GameDamage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_Finished(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK NetDlg_RezFiles(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+void ForceActiveFocus(HWND hWnd);
+void SetIcon(HWND hWnd);
+
+BOOL AddSelToList(HWND hSrcList, HWND hDestList);
+BOOL RemoveSelFromList(HWND hList);
+void UpdateGameLevelControls(HWND hDlg);
+
+void LoadLevelStrings();
+void SaveLevelStrings();
+
+int FillAvailableRez(HWND hList);
+int FillSelectedRez(HWND hList);
+BOOL AddSelectedRez(HWND hSourceList, HWND hDestList);
+BOOL RemoveSelectedRez(HWND hSourceList, HWND hDestList);
+BOOL IsRezSelected(HWND hDestList, const char* sRez);
+BOOL IsSourceItemAddable(HWND hSourceList, HWND hDestList);
+BOOL IsDestItemRemovable(HWND hSourceList, HWND hDestList);
+void UpdateRezControls(HWND hDlg);
+int AddSelectedToList(HWND hDestList);
+void SaveRezStrings();
+void LoadRezStrings();
+void InitGameLevels(HWND hDlg);
+void UpdateSaveGameLevels(HWND hDlg);
+
+BOOL DoOptionHelp(HWND hParentWnd, int iMsg, int iTitle);
+void SetDlgItemFloat(HWND hDlg, int iCtrl, float fValue);
+float GetDlgItemFloat(HWND hDlg, int iCtrl);
+
+void SetItemLevel(HWND hDlg, UINT idControl, int nLevel);
+int GetItemLevel(HWND hDlg, UINT idControl);
+void SetItemRespawn(HWND hDlg, UINT idControl, int nRespawn);
+int GetItemRespawn(HWND hDlg, UINT idControl);
+void SetHealingRate(HWND hDlg, UINT idControl, int nLevel);
+int GetHealingRate(HWND hDlg, UINT idControl);
+
+
+// Functions...
+
+// ----------------------------------------------------------------------- //
+// These functions get/set console variable values.
+// For the Get functions, the value you pass in is used as the default value.
+// ----------------------------------------------------------------------- //
+
+BOOL SetGameVar(const char *pName, const char *pVal)
+{
+ char str[512];
+
+ if(!s_pServerMgr)
+ return FALSE;
+
+ sprintf(str, "\"+%s\" \"%s\"", pName, pVal);
+ s_pServerMgr->RunConsoleString(str);
+ return TRUE;
+}
+
+void SetGameVar(const char *pName, float val)
+{
+ char valStr[256];
+
+ sprintf(valStr, "%f", val);
+ SetGameVar(pName, valStr);
+}
+
+void SetGameVar(const char *pName, int val)
+{
+ char valStr[256];
+
+ sprintf(valStr, "%d", val);
+ SetGameVar(pName, valStr);
+}
+
+
+BOOL NS_GetGameVar(char *pName, char *pVal, DWORD maxLen)
+{
+ HCONSOLEVAR hVar;
+
+ if(!s_pServerMgr)
+ return FALSE;
+
+ if(s_pServerMgr->GetConsoleVar(pName, &hVar, pVal) == LT_OK)
+ {
+ return s_pServerMgr->GetVarValueString(hVar, pVal, maxLen) == LT_OK;
+ }
+ else
+ {
+ return SetGameVar(pName, pVal);
+ }
+}
+
+BOOL NS_GetGameVar(char *pName, int &val)
+{
+ HCONSOLEVAR hVar;
+ char valStr[256];
+
+ if(!s_pServerMgr)
+ return FALSE;
+
+ sprintf(valStr, "%d", val);
+ if(s_pServerMgr->GetConsoleVar(pName, &hVar, valStr) == LT_OK)
+ {
+ if(s_pServerMgr->GetVarValueString(hVar, valStr, sizeof(valStr)) == LT_OK)
+ {
+ val = atoi(valStr);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ return SetGameVar(pName, valStr);
+ }
+}
+
+BOOL NS_GetGameVar(char *pName, float &val)
+{
+ HCONSOLEVAR hVar;
+ char valStr[256];
+
+ if(!s_pServerMgr)
+ return FALSE;
+
+ sprintf(valStr, "%f", val);
+ if(s_pServerMgr->GetConsoleVar(pName, &hVar, valStr) == LT_OK)
+ {
+ if(s_pServerMgr->GetVarValueString(hVar, valStr, sizeof(valStr)) == LT_OK)
+ {
+ val = (float)atof(valStr);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ return SetGameVar(pName, valStr);
+ }
+}
+
+
+// ----------------------------------------------------------------------- //
+// These load/save all the relevant console vars.
+// ----------------------------------------------------------------------- //
+
+void NetStart_LoadConsoleVars()
+{
+ NS_GetGameVar("ServerName", s_sServerName, sizeof(s_sServerName));
+ NS_GetGameVar("ServiceName", s_sServiceName, sizeof(s_sServiceName));
+
+ NS_GetGameVar("GameType", s_nGameType);
+ NS_GetGameVar("EndType", s_nEndType);
+ NS_GetGameVar("EndFrags", s_nEndFrags);
+ NS_GetGameVar("EndTime", s_nEndTime);
+ NS_GetGameVar("NetService", s_nNetService);
+ NS_GetGameVar("MaxPlayers", s_nMaxPlayers);
+ NS_GetGameVar("UpdateInfo", s_bUpdateInfo);
+ NS_GetGameVar("ServerReg", s_bServerReg);
+ NS_GetGameVar("UseGameSpy", s_bUseGameSpy);
+ NS_GetGameVar("DashGoInfo", s_bDashGoInfo);
+ NS_GetGameVar("Port", s_nPort);
+
+ NS_GetGameVar("WorldColorNight", s_pServerOptions->m_sWorldNightColor, sizeof(s_pServerOptions->m_sWorldNightColor));
+ NS_GetGameVar("RunSpeed", s_pServerOptions->m_fRunSpeed);
+ NS_GetGameVar("MissileSpeed", s_pServerOptions->m_fMissileSpeed);
+ NS_GetGameVar("WorldTimeSpeed", s_pServerOptions->m_fWorldTimeSpeed);
+
+ NS_GetGameVar("AmmoLevel", s_nAmmoLevel);
+ NS_GetGameVar("AmmoRespawn", s_nAmmoRespawn);
+ NS_GetGameVar("ArmorLevel", s_nArmorLevel);
+ NS_GetGameVar("ArmorRespawn", s_nArmorRespawn);
+ NS_GetGameVar("HealthLevel", s_nHealthLevel);
+ NS_GetGameVar("HealthRespawn", s_nHealthRespawn);
+ NS_GetGameVar("PowerupsLevel", s_nPowerupsLevel);
+ NS_GetGameVar("PowerupsRespawn", s_nPowerupsRespawn);
+ NS_GetGameVar("HealingRate", s_nHealingRate);
+ NS_GetGameVar("Team", s_nTeam);
+ NS_GetGameVar("FallDamage", s_bFallDamage);
+
+ NS_GetGameVar("FriendlyFire", s_bFriendlyFire);
+ NS_GetGameVar("NegTeamFrags", s_bNegTeamFrags);
+ NS_GetGameVar("OnlyFlagScores", s_bOnlyFlagScores);
+ NS_GetGameVar("OnlyGoalScores", s_bOnlyGoalScores);
+ NS_GetGameVar("UseTeamSize", s_bUseTeamSize);
+ NS_GetGameVar("FlagValue", s_nFlagValue);
+ NS_GetGameVar("GoalValue", s_nGoalValue);
+ NS_GetGameVar("SocBallSkin", s_nSocBallSkin);
+
+#ifndef _ADDON
+ if (s_nGameType == NGT_SOCCER) s_nGameType = NGT_DEATHMATCH;
+#endif
+
+}
+
+void NetStart_SaveConsoleVars()
+{
+ SetGameVar("ServerName", s_sServerName);
+ SetGameVar("ServiceName", s_sServiceName);
+
+ SetGameVar("GameType", s_nGameType);
+ SetGameVar("EndType", s_nEndType);
+ SetGameVar("EndFrags", s_nEndFrags);
+ SetGameVar("EndTime", s_nEndTime);
+ SetGameVar("NetService", s_nNetService);
+ SetGameVar("MaxPlayers", s_nMaxPlayers);
+ SetGameVar("UpdateInfo", s_bUpdateInfo);
+ SetGameVar("ServerReg", s_bServerReg);
+ SetGameVar("UseGameSpy", s_bUseGameSpy);
+ SetGameVar("DashGoInfo", 1);
+ SetGameVar("Port", s_nPort);
+
+ SetGameVar("WorldColorNight", s_pServerOptions->m_sWorldNightColor);
+ SetGameVar("RunSpeed", s_pServerOptions->m_fRunSpeed);
+ SetGameVar("MissileSpeed", s_pServerOptions->m_fMissileSpeed);
+ SetGameVar("WorldTimeSpeed", s_pServerOptions->m_fWorldTimeSpeed);
+
+ SetGameVar("AmmoLevel", s_nAmmoLevel);
+ SetGameVar("AmmoRespawn", s_nAmmoRespawn);
+ SetGameVar("ArmorLevel", s_nArmorLevel);
+ SetGameVar("ArmorRespawn", s_nArmorRespawn);
+ SetGameVar("HealthLevel", s_nHealthLevel);
+ SetGameVar("HealthRespawn", s_nHealthRespawn);
+ SetGameVar("PowerupsLevel", s_nPowerupsLevel);
+ SetGameVar("PowerupsRespawn", s_nPowerupsRespawn);
+ SetGameVar("HealingRate", s_nHealingRate);
+ SetGameVar("Team", s_nTeam);
+ SetGameVar("FallDamage", s_bFallDamage);
+
+ SetGameVar("FriendlyFire", s_bFriendlyFire);
+ SetGameVar("NegTeamFrags", s_bNegTeamFrags);
+ SetGameVar("OnlyFlagScores", s_bOnlyFlagScores);
+ SetGameVar("OnlyGoalScores", s_bOnlyGoalScores);
+ SetGameVar("UseTeamSize", s_bUseTeamSize);
+ SetGameVar("FlagValue", s_nFlagValue);
+ SetGameVar("GoalValue", s_nGoalValue);
+ SetGameVar("SocBallSkin", s_nSocBallSkin);
+}
+
+DRESULT NetStart_SaveConfigFile(char *pFilename)
+{
+ if (!s_pServerMgr)
+ return LT_ERROR;
+
+ return s_pServerMgr->SaveConfigFile(pFilename);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_DoWizard
+//
+// PURPOSE: Starts the multiplayer wizard
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_DoWizard(HINSTANCE hInst, ServerInfo* pServerInfo, ServerOptions* pServerOptions, NetGame* pNetGame, BOOL bNoDlgs, char *pConfig)
+{
+ // Sanity checks...
+
+ if (!pServerInfo) return(FALSE);
+ if (!pServerOptions) return(FALSE);
+ if (!pNetGame) return(FALSE);
+
+
+ // Set our static pointers...
+
+ s_pServerInfo = pServerInfo;
+ s_pServerOptions = pServerOptions;
+ s_pNetGame = pNetGame;
+ s_hInst = hInst;
+
+
+ // Clear the structures...
+
+ memset(s_pServerInfo, 0, sizeof(ServerInfo));
+ memset(s_pServerOptions, 0, sizeof(ServerOptions));
+ memset(s_pNetGame, 0, sizeof(NetGame));
+
+
+ // Fill in the default server options...
+
+ s_pServerOptions->m_fWorldTimeSpeed = -1.0f;
+ s_pServerOptions->m_fRunSpeed = 1.0;
+ s_pServerOptions->m_fMissileSpeed = 1.0;
+
+ strcpy(s_pServerOptions->m_sWorldNightColor, "0.5 0.5 0.5");
+
+
+ // Load some string resources...
+
+#ifdef _ADDON
+ LoadString(s_hInst, IDS_DEFAULTSERVERNAME_AO, s_sServerName, 250);
+#else
+ LoadString(s_hInst, IDS_DEFAULTSERVERNAME, s_sServerName, 250);
+#endif
+
+
+ // Get the server interface...
+
+ s_pServerMgr = GetServerInterface();
+ if (!s_pServerMgr)
+ {
+ return(FALSE);
+ }
+
+
+ // Load the server config file...
+
+ s_pServerMgr->LoadConfigFile(pConfig);
+
+
+ // Declare local variables we'll be using...
+
+ int nRet;
+ int cRezFiles = 0;
+ HWND hParentWnd = NULL;
+ BOOL bAddedResources = FALSE;
+
+
+ // Load our icon...
+
+ s_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+
+ // Init the networking...
+
+ BOOL bRet = s_pServerMgr->InitNetworking(NULL, 0);
+ if (!bRet)
+ {
+ s_nErrorString = IDS_NETERR_INIT;
+ goto Failure;
+ }
+
+
+ // Load some info...
+
+ NetStart_LoadConsoleVars();
+
+ LoadLevelStrings();
+ LoadRezStrings();
+
+
+ // Check if we should skip the dialogs...
+
+ if (bNoDlgs)
+ {
+ if (NetStart_GoNoDialogs(pServerInfo, pNetGame))
+ {
+ return(TRUE);
+ }
+ }
+
+
+ // Do the services dialog...
+
+ServicesDlg:
+ nRet = DialogBox(hInst, "NET_SERVICES", hParentWnd, (DLGPROC)NetDlg_Services);
+
+ if (nRet == DLG_ERROR) goto Failure;
+ if (nRet == DLG_CANCEL) goto Cancel;
+
+
+ // Do the rez files dialog...
+
+RezFilesDlg:
+ cRezFiles = FillAvailableRez(NULL);
+ if (cRezFiles <= 0) goto GameDlg;
+
+ nRet = DialogBox(hInst, "NET_REZFILES", hParentWnd, (DLGPROC)NetDlg_RezFiles);
+
+ if (nRet == DLG_BACK) goto ServicesDlg;
+ if (nRet == DLG_ERROR) goto Failure;
+ if (nRet == DLG_CANCEL) goto Cancel;
+
+
+ // Do the game dialog...
+
+GameDlg:
+
+#ifdef _ADDON
+ nRet = DialogBox(hInst, "NET_GAME_AO", hParentWnd, (DLGPROC)NetDlg_Game);
+#else
+ nRet = DialogBox(hInst, "NET_GAME", hParentWnd, (DLGPROC)NetDlg_Game);
+#endif
+
+ if (nRet == DLG_BACK && cRezFiles <= 0) goto ServicesDlg;
+ if (nRet == DLG_BACK && cRezFiles > 0) goto RezFilesDlg;
+ if (nRet == DLG_ERROR) goto Failure;
+ if (nRet == DLG_CANCEL) goto Cancel;
+
+
+ // If necessary, do the team options dialog...
+
+TeamOptionsDlg:
+ if (s_nGameType != NGT_TEAMS) goto CtfOptionsDlg;
+
+ nRet = DialogBox(hInst, "NET_OPTIONS_TEAMS", hParentWnd, (DLGPROC)NetDlg_TeamOptions);
+
+ if (nRet == DLG_BACK) goto GameDlg;
+ if (nRet == DLG_CANCEL) return(DFALSE);
+ if (nRet == DLG_ERROR) goto Failure;
+
+
+ // If necessary, do the ctf options dialog...
+
+CtfOptionsDlg:
+ if (s_nGameType != NGT_CAPTUREFLAG) goto SoccerOptionsDlg;
+
+ nRet = DialogBox(hInst, "NET_OPTIONS_CTF", hParentWnd, (DLGPROC)NetDlg_CtfOptions);
+
+ if (nRet == DLG_BACK) goto GameDlg;
+ if (nRet == DLG_CANCEL) return(DFALSE);
+ if (nRet == DLG_ERROR) goto Failure;
+
+
+ // If necessary, do the ctf options dialog...
+
+SoccerOptionsDlg:
+ if (s_nGameType != NGT_SOCCER) goto GameItemsDlg;
+
+ nRet = DialogBox(hInst, "NET_OPTIONS_SOCCER", hParentWnd, (DLGPROC)NetDlg_SoccerOptions);
+
+ if (nRet == DLG_BACK) goto GameDlg;
+ if (nRet == DLG_CANCEL) return(DFALSE);
+ if (nRet == DLG_ERROR) goto Failure;
+
+
+ // Do the game items dialog (host only)...
+
+GameItemsDlg:
+ nRet = DialogBox(hInst, "NET_GAMEITEMS", hParentWnd, (DLGPROC)NetDlg_GameItems);
+
+ if (nRet == DLG_BACK)
+ {
+ if (s_nGameType == NGT_SOCCER) goto SoccerOptionsDlg;
+ if (s_nGameType == NGT_CAPTUREFLAG) goto CtfOptionsDlg;
+ if (s_nGameType == NGT_TEAMS) goto TeamOptionsDlg;
+ goto GameDlg;
+ }
+
+ if (nRet == DLG_CANCEL) return(DFALSE);
+ if (nRet == DLG_ERROR) goto Failure;
+
+
+ // Do the game damage dialog (host only)...
+
+GameDamageDlg:
+ nRet = DialogBox(hInst, "NET_GAMEDAMAGE", hParentWnd, (DLGPROC)NetDlg_GameDamage);
+
+ if (nRet == DLG_BACK) goto GameItemsDlg;
+ if (nRet == DLG_CANCEL) return(DFALSE);
+ if (nRet == DLG_ERROR) goto Failure;
+
+
+ // Do the options dialog...
+
+OptionsDlg:
+ nRet = DialogBox(hInst, "NET_OPTIONS", hParentWnd, (DLGPROC)NetDlg_Options);
+
+ if (nRet == DLG_BACK) goto GameDamageDlg;
+ if (nRet == DLG_ERROR) goto Failure;
+ if (nRet == DLG_CANCEL) goto Cancel;
+
+
+ // Do the game levels dialog...
+
+ if (!bAddedResources)
+ {
+ CWaitCursor wc;
+
+ if (!GetTheApp()->AddResources(s_collRezFiles))
+ {
+ goto Failure;
+ }
+
+ bAddedResources = TRUE;
+ }
+
+ nRet = DialogBox(hInst, "NET_GAMELEVELS", hParentWnd, (DLGPROC)NetDlg_GameLevels);
+
+ if (nRet == DLG_BACK) goto OptionsDlg;
+ if (nRet == DLG_ERROR) goto Failure;
+ if (nRet == DLG_CANCEL) goto Cancel;
+
+
+ // Display the "-go" info if we haven't already...
+
+ if (!s_bDashGoInfo)
+ {
+ DoOptionHelp(NULL, IDS_HELP_DASHGO, IDS_TITLE_DASHGO);
+ }
+
+ SaveLevelStrings();
+
+
+ // All done...
+
+ return(TRUE);
+
+
+ // Cancel...
+
+Cancel:
+ return(FALSE);
+
+
+ // Failure...
+
+Failure:
+ NetStart_DisplayError();
+ return(FALSE);
+}
+
+void NetStart_DisplayError()
+{
+ AfxMessageBox(s_nErrorString);
+}
+
+int NetStart_GetPort()
+{
+ return(s_nPort);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_HandleDefaultDialogCommands
+//
+// PURPOSE: Handles default dialog commands (next, back, cancel, etc)
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_HandleDefaultDialogCommands(HWND hDlg, WPARAM wParam)
+{
+ // Handle any default commands...
+
+ switch (wParam)
+ {
+ case IDC_BACK:
+ {
+ EndDialog(hDlg, DLG_BACK);
+ return(TRUE);
+ }
+
+ case IDCANCEL:
+ {
+ EndDialog(hDlg, DLG_CANCEL);
+ return(TRUE);
+ }
+ }
+
+
+ // If we get here, it's not a default command...
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_FillServiceList
+//
+// PURPOSE: Fills a list box with the available services
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_FillServiceList(HWND hList)
+{
+ // Sanity checks...
+
+ if (!hList) return(FALSE);
+ if (!s_pServerMgr) return(FALSE);
+
+
+ // Get the service list...
+
+ NetService *pCur, *pListHead = NULL;
+
+ BOOL bRet = s_pServerMgr->GetServiceList(pListHead);
+ if (!bRet) return(FALSE);
+
+ if (!pListHead)
+ {
+ return(FALSE);
+ }
+
+
+ // Add each service to the list box...
+
+ SendMessage(hList, LB_RESETCONTENT, 0, 0);
+
+ for (pCur=pListHead; pCur; pCur=pCur->m_pNext)
+ {
+ NetService* pService = pCur;
+
+ int iItem = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)pService->m_sName);
+ if (iItem != LB_ERR)
+ {
+ SendMessage(hList, LB_SETITEMDATA, iItem, (LPARAM)pService->m_handle);
+ }
+ }
+
+
+ // Select the last used service...
+
+ int nRet = SendMessage(hList, LB_SETCURSEL, s_nNetService, 0);
+ if (nRet == LB_ERR)
+ {
+ SendMessage(hList, LB_SETCURSEL, 0, 0);
+ }
+
+
+ // Free the service list...
+
+ s_pServerMgr->FreeServiceList(pListHead);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_SelectCurrentService
+//
+// PURPOSE: Selects the currently selected service in the list box
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_SelectCurrentService(HWND hList)
+{
+ // Sanity checks...
+
+ if (!hList) return(FALSE);
+
+
+ // Get the currently select list-box item...
+
+ int nIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+
+ // Get the item data for this index...
+
+ int nRet = SendMessage(hList, LB_GETITEMDATA, nIndex, 0);
+ if (nRet == LB_ERR) return(FALSE);
+
+ HNETSERVICE hNetService = (HNETSERVICE)nRet;
+ if (!hNetService) return(FALSE);
+
+
+ // Select the service...
+
+ BOOL bRet = s_pServerMgr->SelectService(hNetService);
+ if (!bRet) return(FALSE);
+
+ s_nNetService = nIndex;
+
+
+ // Get the string name...
+
+ char sBuf[128];
+ nRet = SendMessage(hList, LB_GETTEXT, nIndex, (LPARAM)sBuf);
+ if (nRet == LB_ERR) s_pServerInfo->m_sService[0] = '\0';
+ else
+ {
+ strcpy(s_pServerInfo->m_sService, sBuf);
+ strcpy(s_sServiceName, s_pServerInfo->m_sService);
+ strlwr(sBuf);
+
+ if (strstr(sBuf, "ipx")) strcpy(s_pServerInfo->m_sService, "Ipx");
+ else if (strstr(sBuf, "modem")) strcpy(s_pServerInfo->m_sService, "Modem");
+ else if (strstr(sBuf, "serial")) strcpy(s_pServerInfo->m_sService, "Serial Cable");
+ else if (strstr(sBuf, "tcp"))
+ {
+ strcpy(s_pServerInfo->m_sService, "Tcp/ip");
+ s_bIsTcpIp = TRUE;
+ }
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_Services
+//
+// PURPOSE: Does the SERVICES dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_Services(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ s_bIsTcpIp = FALSE;
+
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+
+ if (!NetStart_FillServiceList(GetDlgItem(hDlg, IDC_SERVICELIST)))
+ {
+ s_nErrorString = IDS_NETERR_FILLSERVICE;
+ EndDialog(hDlg, DLG_ERROR);
+ }
+
+ CheckDlgButton(hDlg, IDC_USEGAMESPY, s_bUseGameSpy ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_UPDATEINFO, s_bUpdateInfo ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_SERVERREG, s_bServerReg ? BST_CHECKED : BST_UNCHECKED);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ if (!NetStart_SelectCurrentService(GetDlgItem(hDlg, IDC_SERVICELIST)))
+ {
+ s_nErrorString = IDS_NETERR_SELECTSERVICE;
+ EndDialog(hDlg, DLG_ERROR);
+ }
+ else
+ {
+ s_bUpdateInfo = IsDlgButtonChecked(hDlg, IDC_UPDATEINFO) == BST_CHECKED;
+ s_bServerReg = IsDlgButtonChecked(hDlg, IDC_SERVERREG) == BST_CHECKED;
+ s_bUseGameSpy = IsDlgButtonChecked(hDlg, IDC_USEGAMESPY) == BST_CHECKED;
+
+ s_pServerInfo->m_bUseGameSpy = s_bUseGameSpy;
+ s_pServerInfo->m_bUpdateGameInfo = s_bUpdateInfo;
+ s_pServerInfo->m_bRegisterServer = s_bServerReg;
+
+ EndDialog(hDlg, DLG_NEXT);
+ }
+ return(TRUE);
+ }
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_FillGameInfo
+//
+// PURPOSE: Fills the game info from the dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_FillGameInfo(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Get the server name...
+
+ char sName[128];
+ sName[0] = '\0';
+
+ GetDlgItemText(hDlg, IDC_NAME, sName, 120);
+
+ if (strlen(sName) == 0)
+ {
+#ifdef _ADDON
+ LoadString(s_hInst, IDS_DEFAULTSERVERNAME_AO, sName, 124);
+#else
+ LoadString(s_hInst, IDS_DEFAULTSERVERNAME, sName, 124);
+#endif
+ }
+
+ strcpy(s_pServerInfo->m_sName, sName);
+ strcpy(s_sServerName, sName);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_Game
+//
+// PURPOSE: Does the GAME dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_Game(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+ SetDlgItemText(hDlg, IDC_NAME, s_sServerName);
+ NetStart_SetEndGameInfo(hDlg);
+ NetStart_InitGameType(hDlg);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ if (!NetStart_FillGameInfo(hDlg))
+ {
+ EndDialog(hDlg, DLG_ERROR);
+ }
+
+ if (!NetStart_FillGameEnd(hDlg))
+ {
+ EndDialog(hDlg, DLG_ERROR);
+ }
+
+ if (!NetStart_FillGameType(hDlg))
+ {
+ EndDialog(hDlg, DLG_ERROR);
+ }
+
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+void ForceActiveFocus(HWND hWnd)
+{
+ SetActiveWindow(hWnd);
+ BringWindowToTop(hWnd);
+ SetForegroundWindow(hWnd);
+ SetFocus(hWnd);
+}
+
+void SetIcon(HWND hWnd)
+{
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)s_hIcon);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_Welcome
+//
+// PURPOSE: Does the WELCOME dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_Welcome(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+ SetTimer(hDlg, 1, 500, NULL);
+ return(TRUE);
+ }
+
+ case WM_TIMER:
+ {
+ KillTimer(hDlg, 1);
+ ForceActiveFocus(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_Finished
+//
+// PURPOSE: Does the FINISHED dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_Finished(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ KillTimer(hDlg, 1);
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_FillLevelList
+//
+// PURPOSE: Fills a list box with the list of levels
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_FillLevelList(HWND hList, char* sDir, int nData, BOOL bClearList)
+{
+ // Sanity checks...
+
+ if (!hList) return(FALSE);
+ if (!sDir) return(FALSE);
+
+
+ // Get a list of world names and put them in the list box...
+
+ if (bClearList)
+ {
+ SendMessage(hList, LB_RESETCONTENT, 0, 0);
+ }
+
+
+ // Get all the level files in the given directory...
+
+ FileEntry* pFiles = s_pServerMgr->GetFileList(sDir);
+ if (!pFiles) return(FALSE);
+
+ FileEntry* ptr = pFiles;
+
+ while (ptr)
+ {
+ if (ptr->m_Type == TYPE_FILE)
+ {
+ if (strnicmp(&ptr->m_pBaseFilename[strlen(ptr->m_pBaseFilename) - 4], ".dat", 4) == 0)
+ {
+ char sLevel[128];
+ strcpy(sLevel, ptr->m_pBaseFilename);
+ int len = strlen(sLevel);
+ if (len > 4) sLevel[len - 4] = '\0';
+
+ if (NetStart_IsOkToDisplayLevel(sLevel))
+ {
+ int nIndex = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)sLevel);
+ if (nIndex != LB_ERR)
+ {
+ SendMessage(hList, LB_SETITEMDATA, nIndex, nData);
+ }
+ }
+ }
+ }
+
+ ptr = ptr->m_pNext;
+ }
+
+ s_pServerMgr->FreeFileList(pFiles);
+
+
+ // Set the current selection...
+
+ SendMessage(hList, LB_SETCURSEL, 0, 0);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL NetStart_InitGameType(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ CheckDlgButton(hDlg, IDC_BB, s_nGameType == NGT_DEATHMATCH ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CTF, s_nGameType == NGT_CAPTUREFLAG ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_TEAMS, s_nGameType == NGT_TEAMS ? BST_CHECKED : BST_UNCHECKED);
+
+#ifdef _ADDON
+ CheckDlgButton(hDlg, IDC_SOCCER, s_nGameType == NGT_SOCCER ? BST_CHECKED : BST_UNCHECKED);
+#endif
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillGameType(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ if (IsDlgButtonChecked(hDlg, IDC_BB) == BST_CHECKED) s_nGameType = NGT_DEATHMATCH;
+ if (IsDlgButtonChecked(hDlg, IDC_CTF) == BST_CHECKED) s_nGameType = NGT_CAPTUREFLAG;
+ if (IsDlgButtonChecked(hDlg, IDC_TEAMS) == BST_CHECKED) s_nGameType = NGT_TEAMS;
+
+#ifdef _ADDON
+ if (IsDlgButtonChecked(hDlg, IDC_SOCCER) == BST_CHECKED) s_nGameType = NGT_SOCCER;
+#endif
+
+ s_pNetGame->m_byType = s_nGameType;
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GameEnd
+//
+// PURPOSE: Does the GAMEEND dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_GameEnd(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+
+ SetDlgItemInt(hDlg, IDC_MAXPLAYERS, s_nMaxPlayers, FALSE);
+ SetDlgItemInt(hDlg, IDC_FRAGS, s_nEndFrags, FALSE);
+ SetDlgItemInt(hDlg, IDC_MINUTES, s_nEndTime, FALSE);
+ CheckDlgButton(hDlg, IDC_AFTERFRAGS, (s_nEndType == NGE_FRAGS) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_AFTERMINUTES, (s_nEndType == NGE_TIME) ? BST_CHECKED : BST_UNCHECKED);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillGameEnd(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_FillGameEnd
+//
+// PURPOSE: Fills the NetGame structure with the game end info
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_FillGameEnd(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Get the game end type...
+
+ int nType = NGE_NEVER;
+
+ if (IsDlgButtonChecked(hDlg, IDC_AFTERFRAGS) == BST_CHECKED) nType = NGE_FRAGS;
+
+ if (IsDlgButtonChecked(hDlg, IDC_AFTERMINUTES) == BST_CHECKED)
+ {
+ if (nType == NGE_FRAGS) nType = NGE_FRAGSANDTIME;
+ else nType = NGE_TIME;
+ }
+
+ s_pNetGame->m_byEnd = nType;
+ s_nEndType = nType;
+
+
+ // Get the game end value...
+
+ s_nEndFrags = GetDlgItemInt(hDlg, IDC_FRAGS, NULL, FALSE);
+ s_nEndTime = GetDlgItemInt(hDlg, IDC_MINUTES, NULL, FALSE);
+
+ s_pNetGame->m_dwEndTime = s_nEndTime;
+ s_pNetGame->m_dwEndFrags = s_nEndFrags;
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GameLevels
+//
+// PURPOSE: Does the GAMELEVELS dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_GameLevels(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static HWND hRetailList = NULL;
+ static HWND hCustomList = NULL;
+ static HWND hGameList = NULL;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+
+ hRetailList = GetDlgItem(hDlg, IDC_RETAILLIST);
+ hCustomList = GetDlgItem(hDlg, IDC_CUSTOMLIST);
+ hGameList = GetDlgItem(hDlg, IDC_GAMELIST);
+
+ NetStart_FillLevelList(hRetailList, "Worlds\\Multi", RETAIL_LEVEL);
+ NetStart_FillLevelList(hCustomList, "\\", CUSTOM_LEVEL);
+
+#ifdef _ADDON
+ NetStart_FillLevelList(hRetailList, "Worlds_ao\\Multi_ao", ADDON_LEVEL, FALSE);
+#endif
+
+ InitGameLevels(hDlg);
+
+ UpdateGameLevelControls(hDlg);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillGameLevels(hDlg);
+ UpdateSaveGameLevels(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ else if (wParam == IDC_ADDRETAIL)
+ {
+ AddSelToList(hRetailList, hGameList);
+ UpdateGameLevelControls(hDlg);
+ return(TRUE);
+ }
+ else if (wParam == IDC_ADDCUSTOM)
+ {
+ AddSelToList(hCustomList, hGameList);
+ UpdateGameLevelControls(hDlg);
+ return(TRUE);
+ }
+ else if (wParam == IDC_REMOVE)
+ {
+ RemoveSelFromList(hGameList);
+ UpdateGameLevelControls(hDlg);
+ return(TRUE);
+ }
+ else if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ UpdateGameLevelControls(hDlg);
+ return(TRUE);
+ }
+ else if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDC_RETAILLIST: PostMessage(hDlg, WM_COMMAND, IDC_ADDRETAIL, 0); break;
+ case IDC_CUSTOMLIST: PostMessage(hDlg, WM_COMMAND, IDC_ADDCUSTOM, 0); break;
+ case IDC_GAMELIST: PostMessage(hDlg, WM_COMMAND, IDC_REMOVE, 0); break;
+ }
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+void InitGameLevels(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return;
+
+
+ // Get the "save" flag...
+
+ BOOL bSave = FALSE;
+ NS_GetGameVar("SaveGameLevels", bSave);
+ if (!bSave) return;
+
+ CheckDlgButton(hDlg, IDC_SAVE, bSave ? BST_CHECKED : BST_UNCHECKED);
+
+
+ // If we get here, fill in the saved levels...
+
+ HWND hList = GetDlgItem(hDlg, IDC_GAMELIST);
+ if (!hList) return;
+
+ POSITION pos = s_collLevels.GetHeadPosition();
+
+ while (pos)
+ {
+ CString sGameLevel = s_collLevels.GetNext(pos);
+
+ if (!sGameLevel.IsEmpty())
+ {
+ // Prepare the level name by stripping out the prefixes...
+
+ char sLevel[128];
+ char sTemp[128];
+ strcpy(sLevel, sGameLevel);
+ strcpy(sTemp, sGameLevel);
+
+ int nLen = strlen(sTemp);
+
+ if (nLen > 2)
+ {
+ int i = nLen - 1;
+
+ while (i > 0 && sTemp[i] != '\\')
+ {
+ i--;
+ }
+
+ if (i < nLen - 1)
+ {
+ if (sTemp[i] == '\\') i++;
+ strcpy(sLevel, &sTemp[i]);
+ }
+ }
+
+
+ // Add the level to the list...
+
+ int nType = RETAIL_LEVEL;
+
+ strupr(sTemp);
+ if (!strstr(sTemp, "\\MULTI\\") && !strstr(sTemp, "\\MULTI_AO\\"))
+ {
+ nType = CUSTOM_LEVEL;
+ }
+
+#ifdef _ADDON
+ if (strstr(sTemp, "\\MULTI_AO\\"))
+ {
+ nType = ADDON_LEVEL;
+ }
+#endif
+
+ if (NetStart_IsOkToDisplayLevel(sLevel))
+ {
+ int nIndex = SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)sLevel);
+ if (nIndex != LB_ERR) SendMessage(hList, LB_SETITEMDATA, nIndex, nType);
+ }
+ }
+ }
+}
+
+void UpdateSaveGameLevels(HWND hDlg)
+{
+ BOOL bSave = IsDlgButtonChecked(hDlg, IDC_SAVE) == BST_CHECKED;
+ SetGameVar("SaveGameLevels", bSave);
+}
+
+BOOL AddSelToList(HWND hSrcList, HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hSrcList) return(FALSE);
+ if (!hDestList) return(FALSE);
+
+
+ // Get the select item...
+
+ char sText[256];
+ int nData;
+
+ int nIndex = SendMessage(hSrcList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+ int nRet = SendMessage(hSrcList, LB_GETTEXT, nIndex, (LPARAM)(LPSTR)sText);
+ if (nRet == LB_ERR) return(FALSE);
+ if (strlen(sText) <= 0) return(FALSE);
+
+ nData = SendMessage(hSrcList, LB_GETITEMDATA, nIndex, 0);
+ if (nData == LB_ERR) return(FALSE);
+
+
+ // Add the select stuff to the destination list...
+
+ nIndex = SendMessage(hDestList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)sText);
+ if (nIndex == LB_ERR) return(FALSE);
+
+ SendMessage(hDestList, LB_SETITEMDATA, nIndex, nData);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL RemoveSelFromList(HWND hList)
+{
+ // Sanity checks...
+
+ if (!hList) return(FALSE);
+
+
+ // Remove the currently selected item...
+
+ int nIndex = SendMessage(hList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+ int nRet = SendMessage(hList, LB_DELETESTRING, nIndex, 0);
+ if (nRet == LB_ERR) return(FALSE);
+
+
+ // Keep something selected if possible...
+
+ nRet = SendMessage(hList, LB_SETCURSEL, nIndex, 0);
+ if (nRet == LB_ERR && nIndex > 0)
+ {
+ SendMessage(hList, LB_SETCURSEL, nIndex-1, 0);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+void UpdateGameLevelControls(HWND hDlg)
+{
+ // Get the list boxes...
+
+ HWND hRetailList = GetDlgItem(hDlg, IDC_RETAILLIST);
+ HWND hCustomList = GetDlgItem(hDlg, IDC_CUSTOMLIST);
+ HWND hGameList = GetDlgItem(hDlg, IDC_GAMELIST);
+
+
+ // Update the buttons...
+
+ int nRet = SendMessage(hRetailList, LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_ADDRETAIL), nRet != LB_ERR);
+
+ nRet = SendMessage(hCustomList, LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_ADDCUSTOM), nRet != LB_ERR);
+
+ nRet = SendMessage(hGameList, LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_REMOVE), nRet != LB_ERR);
+
+ nRet = SendMessage(hGameList, LB_GETCOUNT, 0, 0);
+ EnableWindow(GetDlgItem(hDlg, IDC_NEXT), nRet > 0);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_FillGameLevels
+//
+// PURPOSE: Fills the level names in the NetGame structure
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_FillGameLevels(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Add each level from the game list...
+
+ s_collLevels.RemoveAll();
+
+ s_pNetGame->m_byNumLevels = 0;
+ for (int j = 0; j < MAX_GAME_LEVELS; j++) s_pNetGame->m_sLevels[j][0] = '\0';
+
+ HWND hList = GetDlgItem(hDlg, IDC_GAMELIST);
+ if (!hList) return(FALSE);
+
+ int nCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
+ if (nCount == LB_ERR) return(FALSE);
+ if (nCount == 0) return(FALSE);
+
+ if (nCount > MAX_GAME_LEVELS) nCount = MAX_GAME_LEVELS;
+
+ for (int i = 0; i < nCount; i++)
+ {
+ char sLevel[128];
+ char sText[128];
+
+ int nRet = SendMessage(hList, LB_GETTEXT, i, (LPARAM)(LPSTR)sText);
+ if (nRet != LB_ERR)
+ {
+ int nData = SendMessage(hList, LB_GETITEMDATA, i, 0);
+
+ if (nData == CUSTOM_LEVEL)
+ {
+ wsprintf(sLevel, "%s", sText);
+ }
+#ifdef _ADDON
+ else if (nData == ADDON_LEVEL)
+ {
+ wsprintf(sLevel, "Worlds_ao\\Multi_ao\\%s", sText);
+ }
+#endif
+ else
+ {
+ wsprintf(sLevel, "Worlds\\Multi\\%s", sText);
+ }
+
+ strcpy(s_pNetGame->m_sLevels[s_pNetGame->m_byNumLevels], sLevel);
+ s_collLevels.AddTail(sLevel);
+ s_pNetGame->m_byNumLevels++;
+ }
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL NetStart_SetEndGameInfo(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ SetDlgItemInt(hDlg, IDC_MAXPLAYERS, s_nMaxPlayers, FALSE);
+ SetDlgItemInt(hDlg, IDC_FRAGS, s_nEndFrags, FALSE);
+ SetDlgItemInt(hDlg, IDC_MINUTES, s_nEndTime, FALSE);
+ CheckDlgButton(hDlg, IDC_AFTERFRAGS, ((s_nEndType == NGE_FRAGS) || (s_nEndType == NGE_FRAGSANDTIME)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_AFTERMINUTES, ((s_nEndType == NGE_TIME) || (s_nEndType == NGE_FRAGSANDTIME)) ? BST_CHECKED : BST_UNCHECKED);
+
+ return(TRUE);
+}
+
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: SaveLevelStrings
+//
+// PURPOSE: Saves all the level strings to the registry
+//
+// ----------------------------------------------------------------------- //
+
+void SaveLevelStrings()
+{
+ // Save the levels...
+
+ POSITION pos = s_collLevels.GetHeadPosition();
+ int count = 0;
+
+ while (pos)
+ {
+ CString sRez = s_collLevels.GetNext(pos);
+ if (!sRez.IsEmpty())
+ {
+ char sLabel[32];
+ wsprintf(sLabel, "Level%i", count);
+ SetGameVar(sLabel, sRez);
+ count++;
+ }
+ }
+
+
+ // Write out the level count...
+
+ SetGameVar("NumLevels", count);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: LoadLevelStrings
+//
+// PURPOSE: Loads all the level strings from the registry
+//
+// ----------------------------------------------------------------------- //
+
+void LoadLevelStrings()
+{
+ // Load the level count...
+
+ int count = 0;
+ NS_GetGameVar("NumLevels", count);
+
+
+ // Load the strings...
+
+ s_collLevels.RemoveAll();
+
+ for (int i = 0; i < count; i++)
+ {
+ char sLabel[32];
+ char sLevel[128];
+ wsprintf(sLabel, "Level%i", i);
+ strcpy(sLevel, "");
+
+ NS_GetGameVar(sLabel, sLevel, 120);
+
+ if (sLevel[0] != '\0')
+ {
+ s_collLevels.AddTail(sLevel);
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GoNoDialogs
+//
+// PURPOSE: Sets everything up using saved values instead of dialogs
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_GoNoDialogs(ServerInfo* pServerInfo, NetGame* pNetGame)
+{
+ // Sanity checks...
+
+ if (!pServerInfo) return(FALSE);
+ if (!pNetGame) return(FALSE);
+
+
+ // Make sure we have a service name...
+
+ if (strlen(s_sServiceName) <= 0) return(FALSE);
+
+
+ // Make sure we have some levels...
+
+ if (s_collLevels.GetCount() <= 0) return(FALSE);
+
+
+ // Get the service list...
+
+ NetService *pCur, *pListHead = NULL;
+
+ BOOL bRet = s_pServerMgr->GetServiceList(pListHead);
+ if (!bRet) return(FALSE);
+
+ if (!pListHead)
+ {
+ return(FALSE);
+ }
+
+
+ // Find the service we want...
+
+ int nIndex = -1;
+ NetService *pFound = NULL;
+
+ for (pCur=pListHead; pCur; pCur=pCur->m_pNext)
+ {
+ if (stricmp(pCur->m_sName, s_sServiceName) == 0)
+ {
+ pFound = pCur;
+ break;
+ }
+ }
+
+ if (!pFound)
+ {
+ s_pServerMgr->FreeServiceList(pListHead);
+ return(FALSE);
+ }
+
+ NetService* pService = pFound;
+ HNETSERVICE hNetService = pService->m_handle;
+
+ s_pServerMgr->FreeServiceList(pListHead);
+
+
+ // Select the service...
+
+ bRet = s_pServerMgr->SelectService(hNetService);
+ if (!bRet) return(FALSE);
+
+ strcpy(s_pServerInfo->m_sService, s_sServiceName);
+ strlwr(s_pServerInfo->m_sService);
+
+ if (strstr(s_pServerInfo->m_sService, "ipx")) strcpy(s_pServerInfo->m_sService, "Ipx");
+ else if (strstr(s_pServerInfo->m_sService, "tcp")) strcpy(s_pServerInfo->m_sService, "Tcp/ip");
+ else if (strstr(s_pServerInfo->m_sService, "modem")) strcpy(s_pServerInfo->m_sService, "Modem");
+ else if (strstr(s_pServerInfo->m_sService, "serial")) strcpy(s_pServerInfo->m_sService, "Serial Cable");
+
+
+ // Fill in the update options...
+
+ pServerInfo->m_bUpdateGameInfo = s_bUpdateInfo;
+ pServerInfo->m_bRegisterServer = s_bServerReg;
+ pServerInfo->m_bUseGameSpy = s_bUseGameSpy;
+
+
+ // Set the server name...
+
+ strcpy(pServerInfo->m_sName, s_sServerName);
+
+
+ // Get the max players...
+
+ pServerInfo->m_dwMaxPlayers = s_nMaxPlayers;
+
+
+ // Set the game end info...
+
+ pNetGame->m_byType = s_nGameType;
+ pNetGame->m_byEnd = s_nEndType;
+ pNetGame->m_dwEndTime = s_nEndTime;
+ pNetGame->m_dwEndFrags = s_nEndFrags;
+
+
+ // Set the other game options...
+
+ pNetGame->m_nAmmoLevel = s_nAmmoLevel;
+ pNetGame->m_nAmmoRespawn = s_nAmmoRespawn;
+ pNetGame->m_nArmorLevel = s_nArmorLevel;
+ pNetGame->m_nArmorRespawn = s_nArmorRespawn;
+ pNetGame->m_nHealthLevel = s_nHealthLevel;
+ pNetGame->m_nHealthRespawn = s_nHealthRespawn;
+ pNetGame->m_nPowerupsLevel = s_nPowerupsLevel;
+ pNetGame->m_nPowerupsRespawn = s_nPowerupsRespawn;
+ pNetGame->m_nHealingRate = s_nHealingRate;
+ pNetGame->m_bFallDamage = s_bFallDamage;
+
+ pNetGame->m_bFriendlyFire = s_bFriendlyFire;
+ pNetGame->m_bNegTeamFrags = s_bNegTeamFrags;
+ pNetGame->m_bOnlyFlagScores = s_bOnlyFlagScores;
+ pNetGame->m_bOnlyGoalScores = s_bOnlyGoalScores;
+ pNetGame->m_bUseTeamSize = s_bUseTeamSize;
+ pNetGame->m_nFlagValue = s_nFlagValue;
+ pNetGame->m_nGoalValue = s_nGoalValue;
+ pNetGame->m_nSocBallSkin = s_nSocBallSkin;
+
+
+ // Add the resources...
+
+ if (!GetTheApp()->AddResources(s_collRezFiles))
+ {
+ return(FALSE);
+ }
+
+
+ // Add each level from our collection...
+
+ pNetGame->m_byNumLevels = 0;
+ for (int j = 0; j < MAX_GAME_LEVELS; j++) s_pNetGame->m_sLevels[j][0] = '\0';
+
+ int nCount = s_collLevels.GetCount();
+
+ POSITION pos = s_collLevels.GetHeadPosition();
+ if (!pos) return(FALSE);
+
+ while (pos)
+ {
+ CString sLevel = s_collLevels.GetNext(pos);
+ strcpy(pNetGame->m_sLevels[pNetGame->m_byNumLevels], sLevel);
+ pNetGame->m_byNumLevels++;
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_RezFiles
+//
+// PURPOSE: Does the REZFILES dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_RezFiles(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+
+ if (FillAvailableRez(GetDlgItem(hDlg, IDC_SOURCELIST)) <= 0)
+ {
+ EndDialog(hDlg, DLG_NEXT);
+ }
+
+ FillSelectedRez(GetDlgItem(hDlg, IDC_DESTLIST));
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ KillTimer(hDlg, 1);
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ AddSelectedToList(GetDlgItem(hDlg, IDC_DESTLIST));
+ SaveRezStrings();
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ else if (wParam == IDC_ADD)
+ {
+ AddSelectedRez(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ UpdateRezControls(hDlg);
+ }
+ else if (wParam == IDC_REMOVE)
+ {
+ RemoveSelectedRez(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ UpdateRezControls(hDlg);
+ }
+ else if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ UpdateRezControls(hDlg);
+ }
+ else if (HIWORD(wParam) == LBN_DBLCLK)
+ {
+ if (LOWORD(wParam) == IDC_SOURCELIST)
+ {
+ AddSelectedRez(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ UpdateRezControls(hDlg);
+ }
+ else if (LOWORD(wParam) == IDC_DESTLIST)
+ {
+ RemoveSelectedRez(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ UpdateRezControls(hDlg);
+ }
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: FillAvailableRez
+//
+// PURPOSE: Fills the given list box with the available rez files
+//
+// ----------------------------------------------------------------------- //
+
+int FillAvailableRez(HWND hList)
+{
+ // Remove the current list contents...
+
+ if (hList) SendMessage(hList, LB_RESETCONTENT, 0, 0);
+
+
+ // Change to the "custom" direcotry...
+
+ if (chdir("Custom") != 0) return(0);
+
+
+ // Enumerate the available rez files and add them to the list box...
+
+ int count = 0;
+ long hFile;
+ struct _finddata_t fd;
+
+ hFile = _findfirst("*.rez", &fd);
+ if (hFile == -1)
+ {
+ chdir ("..");
+ return(0);
+ }
+
+ if (hList) SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)fd.name);
+ count++;
+
+ BOOL bContinue = TRUE;
+
+ while (bContinue)
+ {
+ if (_findnext(hFile, &fd) != 0)
+ {
+ bContinue = FALSE;
+ }
+ else
+ {
+ if (hList) SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)fd.name);
+ count++;
+ }
+ }
+
+
+ // Restore the directory...
+
+ chdir ("..");
+
+
+ // All done...
+
+ return(count);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: FillSelectedRez
+//
+// PURPOSE: Fills the given list box with the selected rez files
+//
+// ----------------------------------------------------------------------- //
+
+int FillSelectedRez(HWND hList)
+{
+ // Sanity checks...
+
+ if (!hList) return(0);
+
+
+ // Remove the current list contents...
+
+ SendMessage(hList, LB_RESETCONTENT, 0, 0);
+
+
+ // Enumerate the selected rez files and add them to the list box...
+
+ POSITION pos = s_collRezFiles.GetHeadPosition();
+ int count = 0;
+
+ while (pos)
+ {
+ CString sRez = s_collRezFiles.GetNext(pos);
+
+ char sTemp[128];
+ strncpy(sTemp, sRez, 125);
+ strupr(sTemp);
+ if (strncmp(sTemp, "CUSTOM\\", 7) == 0)
+ {
+ strncpy(sTemp, sRez, 125);
+ sRez = &sTemp[7];
+ }
+
+ SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)sRez);
+ count++;
+ }
+
+
+ // All done...
+
+ return(count);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: AddSelectedRez
+//
+// PURPOSE: Adds the selected source rez to the dest list
+//
+// ----------------------------------------------------------------------- //
+
+BOOL AddSelectedRez(HWND hSourceList, HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hSourceList) return(FALSE);
+ if (!hDestList) return(FALSE);
+
+
+ // Get the selected item from the source list...
+
+ int nIndex = SendMessage(hSourceList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+ char sRez[256];
+ int nRet = SendMessage(hSourceList, LB_GETTEXT, nIndex, (LPARAM)(LPCSTR)sRez);
+ if (nRet == LB_ERR) return(FALSE);
+
+
+ // Check if this rez is already selected...
+
+ if (IsRezSelected(hDestList, sRez))
+ {
+ return(TRUE);
+ }
+
+
+ // Add the selected string to our list...
+
+ nRet = SendMessage(hDestList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)sRez);
+ if (nRet == LB_ERR) return(FALSE);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: RemoveSelectedRez
+//
+// PURPOSE: Removes the selected dest rez to the dest list
+//
+// ----------------------------------------------------------------------- //
+
+BOOL RemoveSelectedRez(HWND hSourceList, HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hSourceList) return(FALSE);
+ if (!hDestList) return(FALSE);
+
+
+ // Get the selected rez in the dest list...
+
+ int nIndex = SendMessage(hDestList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+
+ // Remove the current item from the dest list...
+
+ int nRet = SendMessage(hDestList, LB_DELETESTRING, nIndex, 0);
+ if (!nRet == LB_ERR) return(FALSE);
+
+
+ // Try to select the previous item...
+
+ nRet = SendMessage(hDestList, LB_SETCURSEL, nIndex, 0);
+ if (nRet == LB_ERR && nIndex > 0)
+ {
+ SendMessage(hDestList, LB_SETCURSEL, nIndex-1, 0);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: IsRezSelected
+//
+// PURPOSE: Determines if the given rez is in the dest list
+//
+// ----------------------------------------------------------------------- //
+
+BOOL IsRezSelected(HWND hDestList, const char* sRez)
+{
+ // Sanity checks...
+
+ if (!hDestList) return(FALSE);
+ if (!sRez) return(FALSE);
+
+
+ // Look for this string in the list...
+
+ int nCount = SendMessage(hDestList, LB_GETCOUNT, 0, 0);
+ if (nCount == LB_ERR) return(FALSE);
+
+ for (int i = 0; i < nCount; i++)
+ {
+ char sText[256];
+
+ int nRet = SendMessage(hDestList, LB_GETTEXT, i, (LPARAM)(LPSTR)sText);
+ if (nRet != LB_ERR)
+ {
+ if (strcmp(sRez, sText) == 0) return(TRUE);
+ }
+ }
+
+
+ // If we get here, we didn't find this rez...
+
+ return(FALSE);
+}
+
+BOOL IsSourceItemAddable(HWND hSourceList, HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hSourceList) return(FALSE);
+ if (!hDestList) return(FALSE);
+
+
+ // Get the selected rez in the source list...
+
+ int nIndex = SendMessage(hSourceList, LB_GETCURSEL, 0, 0);
+ if (nIndex == LB_ERR) return(FALSE);
+
+ char sRez[256];
+ int nRet = SendMessage(hSourceList, LB_GETTEXT, nIndex, (LPARAM)(LPCSTR)sRez);
+ if (nRet == LB_ERR) return(FALSE);
+
+
+ // Determine if this rez is already selected...
+
+ return(!IsRezSelected(hDestList, sRez));
+}
+
+BOOL IsDestItemRemovable(HWND hSourceList, HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hSourceList) return(FALSE);
+ if (!hDestList) return(FALSE);
+
+
+ // Get the selected rez in the dest list...
+
+ int nIndex = SendMessage(hDestList, LB_GETCURSEL, 0, 0);
+ return (nIndex != LB_ERR);
+}
+
+void UpdateRezControls(HWND hDlg)
+{
+ if (!hDlg) return;
+
+ BOOL bAddable = IsSourceItemAddable(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ EnableWindow(GetDlgItem(hDlg, IDC_ADD), bAddable);
+
+ BOOL bRemable = IsDestItemRemovable(GetDlgItem(hDlg, IDC_SOURCELIST), GetDlgItem(hDlg, IDC_DESTLIST));
+ EnableWindow(GetDlgItem(hDlg, IDC_REMOVE), bRemable);
+}
+
+int AddSelectedToList(HWND hDestList)
+{
+ // Sanity checks...
+
+ if (!hDestList) return(0);
+
+
+ // Remove all the items from the current string list...
+
+ s_collRezFiles.RemoveAll();
+
+
+ // Add each item in the list box to our string list...
+
+ int nCount = SendMessage(hDestList, LB_GETCOUNT, 0, 0);
+ if (nCount == LB_ERR) return(0);
+
+ int c = 0;
+
+ for (int i = 0; i < nCount; i++)
+ {
+ char sRez[256];
+ int nRet = SendMessage(hDestList, LB_GETTEXT, i, (LPARAM)(LPCSTR)sRez);
+ if (nRet != LB_ERR)
+ {
+ if (strstr(sRez, "\\"))
+ {
+ s_collRezFiles.AddTail(sRez);
+ }
+ else
+ {
+ char sTemp[256];
+ sprintf(sTemp, "Custom\\%s", sRez);
+ s_collRezFiles.AddTail(sTemp);
+ }
+ c++;
+ }
+ }
+
+
+ // All done...
+
+ return(c);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: SaveRezStrings
+//
+// PURPOSE: Saves all the strings to the registry if requested
+//
+// ----------------------------------------------------------------------- //
+
+void SaveRezStrings()
+{
+ // Save each rez file string...
+
+ POSITION pos = s_collRezFiles.GetHeadPosition();
+ int nCount = 0;
+
+ while (pos)
+ {
+ CString sRez = s_collRezFiles.GetNext(pos);
+ if (!sRez.IsEmpty())
+ {
+ char sLabel[32];
+ sprintf(sLabel, "RezFile%i", nCount);
+ SetGameVar(sLabel, sRez);
+ nCount++;
+ }
+ }
+
+ // Save the count of strings...
+
+ SetGameVar("NumRezFiles", nCount);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: LoadRezStrings
+//
+// PURPOSE: Loads all the strings from the registry if requested
+//
+// ----------------------------------------------------------------------- //
+
+void LoadRezStrings()
+{
+ // Clear the list of rez files...
+
+ s_collRezFiles.RemoveAll();
+
+
+ // Load the count of rez strings...
+
+ int nCount = 0;
+
+ if (!NS_GetGameVar("NumRezFiles", nCount)) return;
+ if (nCount <= 0) return;
+
+
+ // Load the strings...
+
+ for (int i = 0; i < nCount; i++)
+ {
+ char sLabel[32];
+ sprintf(sLabel, "RezFile%i", i);
+
+ char sRez[128] = { "" };
+ NS_GetGameVar(sLabel, sRez, 125);
+
+ if (sRez[0] != '\0')
+ {
+ s_collRezFiles.AddTail(sRez);
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_Options
+//
+// PURPOSE: Does the OPTIONS dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_Options(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetIcon(hDlg);
+ ForceActiveFocus(hDlg);
+ NetStart_InitOptions(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillOptions(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_RUNSPEED)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_RUNSPEED, IDS_TITLE_RUNSPEED);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_MISSILESPEED)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_MISSILESPEED, IDS_TITLE_MISSILESPEED);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_TIMESPEED)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_TIMESPEED, IDS_TITLE_TIMESPEED);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_NIGHTCOLOR)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_NIGHTCOLOR, IDS_TITLE_NIGHTCOLOR);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_RESPAWNSCALE)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_RESPAWNSCALE, IDS_TITLE_RESPAWNSCALE);
+ return(TRUE);
+ }
+ else if (wParam == IDC_HELP_HEALSCALE)
+ {
+ DoOptionHelp(hDlg, IDS_HELP_HEALSCALE, IDS_TITLE_HEALSCALE);
+ return(TRUE);
+ }
+ else if (wParam == IDC_COLORPICKER)
+ {
+ if (NetStart_GetWorldNightColor(NULL))
+ {
+ SetDlgItemText(hDlg, IDC_NIGHTCOLOR, s_pServerOptions->m_sWorldNightColor);
+ }
+ return(TRUE);
+ }
+
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+BOOL DoOptionHelp(HWND hParentWnd, int iMsg, int iTitle)
+{
+ if (!s_hInst) s_hInst = GetModuleHandle(NULL);
+
+ char sMsg[256];
+ if (LoadString(s_hInst, iMsg, sMsg, 250) == 0) return(FALSE);
+
+ char sTitle[128];
+ if (LoadString(s_hInst, iTitle, sTitle, 125) == 0) return(FALSE);
+
+ MessageBox(hParentWnd, sMsg, sTitle, MB_OK | MB_ICONINFORMATION);
+
+ return(TRUE);
+}
+
+BOOL NetStart_InitOptions(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+ if (!s_pServerOptions) return(FALSE);
+
+ if (s_bIsTcpIp)
+ {
+ ShowWindow(GetDlgItem(hDlg, IDC_PORTNUMTEXT), SW_SHOW);
+ ShowWindow(GetDlgItem(hDlg, IDC_PORTNUM), SW_SHOW);
+
+ SetDlgItemInt(hDlg, IDC_PORTNUM, s_nPort, FALSE);
+ }
+ else
+ {
+ ShowWindow(GetDlgItem(hDlg, IDC_PORTNUMTEXT), SW_HIDE);
+ ShowWindow(GetDlgItem(hDlg, IDC_PORTNUM), SW_HIDE);
+ }
+
+ SetDlgItemFloat(hDlg, IDC_RUNSPEED, s_pServerOptions->m_fRunSpeed);
+ SetDlgItemFloat(hDlg, IDC_MISSILESPEED, s_pServerOptions->m_fMissileSpeed);
+
+ SetDlgItemText(hDlg, IDC_NIGHTCOLOR, s_pServerOptions->m_sWorldNightColor);
+
+ float fTime = s_pServerOptions->m_fWorldTimeSpeed;
+ SetDlgItemFloat(hDlg, IDC_TIMESPEED, fTime);
+
+ SetDlgItemInt(hDlg, IDC_MAXPLAYERS, s_nMaxPlayers, FALSE);
+
+ return(TRUE);
+}
+
+void SetDlgItemFloat(HWND hDlg, int iCtrl, float fValue)
+{
+ char sBuf[64];
+ sprintf(sBuf, "%f", fValue);
+ SetDlgItemText(hDlg, iCtrl, sBuf);
+}
+
+float GetDlgItemFloat(HWND hDlg, int iCtrl)
+{
+ char sBuf[64];
+ GetDlgItemText(hDlg, iCtrl, sBuf, 62);
+ return((float)atof(sBuf));
+}
+
+BOOL NetStart_FillOptions(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+ if (!s_pServerOptions) return(FALSE);
+
+ s_pServerOptions->m_fRunSpeed = GetDlgItemFloat(hDlg, IDC_RUNSPEED);
+ s_pServerOptions->m_fMissileSpeed = GetDlgItemFloat(hDlg, IDC_MISSILESPEED);
+
+ GetDlgItemText(hDlg, IDC_NIGHTCOLOR, s_pServerOptions->m_sWorldNightColor, 30);
+
+ s_nPort = 0;
+ s_nPort = GetDlgItemInt(hDlg, IDC_PORT, NULL, FALSE);
+
+ float fTime = GetDlgItemFloat(hDlg, IDC_TIMESPEED);
+ if (fTime != 0) s_pServerOptions->m_fWorldTimeSpeed = fTime;
+
+ s_nMaxPlayers = GetDlgItemInt(hDlg, IDC_MAXPLAYERS, NULL, FALSE);
+ if (s_nMaxPlayers <= 0) s_nMaxPlayers = 2;
+ if (s_nMaxPlayers >= MAX_MULTI_PLAYERS) s_nMaxPlayers = MAX_MULTI_PLAYERS;
+ s_pServerInfo->m_dwMaxPlayers = s_nMaxPlayers;
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_RunServerOptions
+//
+// PURPOSE: Runs all of the server options
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_RunServerOptions(ServerInterface* pServerMgr, ServerOptions* pServerOptions)
+{
+ // Sanity checks...
+
+ if (!pServerMgr) return(FALSE);
+ if (!pServerOptions) return(FALSE);
+
+ return(TRUE); // no more server options for now
+
+
+ // Run the speed options...
+
+ char sBuf[128];
+
+ if (pServerOptions->m_fRunSpeed != 0)
+ {
+ sprintf(sBuf, "RunSpeed %f", pServerOptions->m_fRunSpeed);
+ pServerMgr->RunConsoleString(sBuf);
+ }
+
+ if (pServerOptions->m_fMissileSpeed != 0)
+ {
+ sprintf(sBuf, "MissileSpeed %f", pServerOptions->m_fMissileSpeed);
+ pServerMgr->RunConsoleString(sBuf);
+ }
+
+
+ // Run the world options...
+
+ if (pServerOptions->m_fWorldTimeSpeed != 0)
+ {
+ sprintf(sBuf, "WorldTimeSpeed %f", pServerOptions->m_fWorldTimeSpeed);
+ pServerMgr->RunConsoleString(sBuf);
+ }
+
+ if (pServerOptions->m_sWorldNightColor[0] != '\0')
+ {
+ sprintf(sBuf, "WorldColorNight \"%s\"", pServerOptions->m_sWorldNightColor);
+ pServerMgr->RunConsoleString(sBuf);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_DoOptionsDialog
+//
+// PURPOSE: Does the options dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_DoOptionsDialog(HWND hParentWnd, ServerInterface* pServerMgr, ServerOptions* pServerOptions)
+{
+ // Sanity checks...
+
+ if (!pServerMgr) return(FALSE);
+ if (!pServerOptions) return(FALSE);
+
+
+ // Do the dialog...
+
+ if (!s_hInst) s_hInst = GetModuleHandle(NULL);
+
+ int nRet = DialogBox(s_hInst, "SERVER_OPTIONS", hParentWnd, (DLGPROC)NetDlg_Options);
+ if (nRet != DLG_NEXT) return(FALSE);
+
+
+ // Run the console options...
+
+ if (!NetStart_RunServerOptions(pServerMgr, pServerOptions))
+ {
+ return(FALSE);
+ }
+
+ SetGameVar("WorldNightColor", s_pServerOptions->m_sWorldNightColor);
+ SetGameVar("RunSpeed", s_pServerOptions->m_fRunSpeed);
+ SetGameVar("MissileSpeed", s_pServerOptions->m_fMissileSpeed);
+ SetGameVar("TimeSpeed", s_pServerOptions->m_fWorldTimeSpeed);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GetWorldNightColor
+//
+// PURPOSE: Gets the world night color via a color dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_GetWorldNightColor(HWND hParenWnd)
+{
+ // Do the color dialog...
+
+ CColorDialog dlg;
+
+ int nRet = dlg.DoModal();
+ if (nRet != IDOK) return(FALSE);
+
+
+ // Update the color...
+
+ COLORREF cr = dlg.GetColor();
+
+ BYTE byRed = (BYTE)(cr);
+ BYTE byGreen = (BYTE)(cr >> 8);
+ BYTE byBlue = (BYTE)(cr >> 16);
+
+ float fRed = (float)byRed / 255.0f;
+ float fGreen = (float)byGreen / 255.0f;
+ float fBlue = (float)byBlue / 255.0f;
+
+ sprintf(s_pServerOptions->m_sWorldNightColor, "%.2f %.2f %.2f", fRed, fGreen, fBlue);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GameItems
+//
+// PURPOSE: Does the GAMEITEMS dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_GameItems(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ ForceActiveFocus(hDlg);
+
+ NetStart_InitGameItems(hDlg);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillGameItems(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+BOOL NetStart_InitGameItems(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ SetItemLevel(hDlg, IDC_AMMO_LEVEL, s_nAmmoLevel);
+ SetItemLevel(hDlg, IDC_ARMOR_LEVEL, s_nArmorLevel);
+ SetItemLevel(hDlg, IDC_HEALTH_LEVEL, s_nHealthLevel);
+ SetItemLevel(hDlg, IDC_POWERUPS_LEVEL, s_nPowerupsLevel);
+
+ SetItemRespawn(hDlg, IDC_AMMO_RESPAWN, s_nAmmoRespawn);
+ SetItemRespawn(hDlg, IDC_ARMOR_RESPAWN, s_nArmorRespawn);
+ SetItemRespawn(hDlg, IDC_HEALTH_RESPAWN, s_nHealthRespawn);
+ SetItemRespawn(hDlg, IDC_POWERUPS_RESPAWN, s_nPowerupsRespawn);
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillGameItems(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ s_nAmmoLevel = GetItemLevel(hDlg, IDC_AMMO_LEVEL);
+ s_nArmorLevel = GetItemLevel(hDlg, IDC_ARMOR_LEVEL);
+ s_nHealthLevel = GetItemLevel(hDlg, IDC_HEALTH_LEVEL);
+ s_nPowerupsLevel = GetItemLevel(hDlg, IDC_POWERUPS_LEVEL);
+
+ s_nAmmoRespawn = GetItemRespawn(hDlg, IDC_AMMO_RESPAWN);
+ s_nArmorRespawn = GetItemRespawn(hDlg, IDC_ARMOR_RESPAWN);
+ s_nHealthRespawn = GetItemRespawn(hDlg, IDC_HEALTH_RESPAWN);
+ s_nPowerupsRespawn = GetItemRespawn(hDlg, IDC_POWERUPS_RESPAWN);
+
+ if (s_nAmmoLevel >= 0) s_pNetGame->m_nAmmoLevel = s_nAmmoLevel;
+ if (s_nAmmoRespawn >= 0) s_pNetGame->m_nAmmoRespawn = s_nAmmoRespawn;
+
+ if (s_nArmorLevel >= 0) s_pNetGame->m_nArmorLevel = s_nArmorLevel;
+ if (s_nArmorRespawn >= 0) s_pNetGame->m_nArmorRespawn = s_nArmorRespawn;
+
+ if (s_nHealthLevel >= 0) s_pNetGame->m_nHealthLevel = s_nHealthLevel;
+ if (s_nHealthRespawn >= 0) s_pNetGame->m_nHealthRespawn = s_nHealthRespawn;
+
+ if (s_nPowerupsLevel >= 0) s_pNetGame->m_nPowerupsLevel = s_nPowerupsLevel;
+ if (s_nPowerupsRespawn >= 0) s_pNetGame->m_nPowerupsRespawn = s_nPowerupsRespawn;
+
+ return(TRUE);
+}
+
+void AddComboString(HWND hCombo, int nStringID)
+{
+ if (!hCombo) return;
+ if (!s_hInst) return;
+
+ char sTemp[128];
+ if (LoadString(s_hInst, nStringID, sTemp, 125) <= 0) return;
+
+ SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)sTemp);
+}
+
+void SetItemLevel(HWND hDlg, UINT idControl, int nLevel)
+{
+ if (!hDlg) return;
+ HWND hCombo = GetDlgItem(hDlg, idControl);
+ if (!hCombo) return;
+
+
+ SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
+
+ AddComboString(hCombo, IDS_NETWIZ_ITEMS_NONE); // "None"
+ AddComboString(hCombo, IDS_NETWIZ_ITEMS_HALF); // "Half"
+ AddComboString(hCombo, IDS_NETWIZ_ITEMS_NORMAL); // "Normal"
+ AddComboString(hCombo, IDS_NETWIZ_ITEMS_DOUBLE); // "Double"
+ AddComboString(hCombo, IDS_NETWIZ_ITEMS_INSANE); // "Insane"
+
+ SendMessage(hCombo, CB_SETCURSEL, nLevel, 0);
+}
+
+int GetItemLevel(HWND hDlg, UINT idControl)
+{
+ if (!hDlg) return(-1);
+ HWND hCombo = GetDlgItem(hDlg, idControl);
+ if (!hCombo) return(-1);
+
+ return(SendMessage(hCombo, CB_GETCURSEL, 0, 0));
+}
+
+void SetItemRespawn(HWND hDlg, UINT idControl, int nRespawn)
+{
+ if (!hDlg) return;
+
+ SetDlgItemInt(hDlg, idControl, nRespawn, FALSE);
+}
+
+int GetItemRespawn(HWND hDlg, UINT idControl)
+{
+ if (!hDlg) return(-1);
+
+ return(GetDlgItemInt(hDlg, idControl, NULL, FALSE));
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_GameDamage
+//
+// PURPOSE: Does the GAMEDAMAGE dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_GameDamage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ ForceActiveFocus(hDlg);
+
+ NetStart_InitGameDamage(hDlg);
+
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillGameDamage(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+BOOL NetStart_InitGameDamage(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ SetHealingRate(hDlg, IDC_HEALRATE, s_nHealingRate);
+ CheckDlgButton(hDlg, IDC_FALLDAMAGE, s_bFallDamage ? BST_CHECKED : BST_UNCHECKED);
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillGameDamage(HWND hDlg)
+{
+ if (!hDlg) return(FALSE);
+
+ s_nHealingRate = GetHealingRate(hDlg, IDC_HEALRATE);
+ s_bFallDamage = IsDlgButtonChecked(hDlg, IDC_FALLDAMAGE) == BST_CHECKED;
+
+ s_pNetGame->m_nHealingRate = s_nHealingRate;
+ s_pNetGame->m_bFallDamage = s_bFallDamage;
+
+ return(TRUE);
+}
+
+void SetHealingRate(HWND hDlg, UINT idControl, int nLevel)
+{
+ if (!hDlg) return;
+ HWND hCombo = GetDlgItem(hDlg, idControl);
+ if (!hCombo) return;
+
+ SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
+
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_NOHEALING); // "No Healing"
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_REALLYSLOW); // "Really Slow"
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_SLOW); // "Slow"
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_NORMAL); // "Normal"
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_FAST); // "Fast"
+ AddComboString(hCombo, IDS_NETWIZ_HEAL_REALLYFAST); // "Really Fast"
+
+ SendMessage(hCombo, CB_SETCURSEL, nLevel, 0);
+}
+
+int GetHealingRate(HWND hDlg, UINT idControl)
+{
+ if (!hDlg) return(-1);
+ HWND hCombo = GetDlgItem(hDlg, idControl);
+ if (!hCombo) return(-1);
+
+ return(SendMessage(hCombo, CB_GETCURSEL, 0, 0));
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_IsOkToDisplayLevel
+//
+// PURPOSE: Determines if it's ok to display the given level in the
+// level list.
+//
+// ----------------------------------------------------------------------- //
+
+BOOL NetStart_IsOkToDisplayLevel(char* sLevel)
+{
+ // Sanity checks...
+
+ if (!sLevel) return(FALSE);
+
+
+ // Determine the prefix to look for based on the game type...
+
+ char sPrefix[32] = { "BB" };
+
+ switch (s_nGameType)
+ {
+ case NGT_DEATHMATCH: strcpy(sPrefix, "BB"); break;
+ case NGT_CAPTUREFLAG: strcpy(sPrefix, "CTF"); break;
+ case NGT_TEAMS: strcpy(sPrefix, "BB"); break;
+ case NGT_SOCCER: strcpy(sPrefix, "SOC"); break;
+ }
+
+
+ // Check for the prefix we need...
+
+ char sTemp[128];
+
+ strncpy(sTemp, sLevel, 126);
+ strupr(sTemp);
+
+ if (strncmp(sTemp, sPrefix, strlen(sPrefix)) != 0)
+ {
+ return(FALSE);
+ }
+
+
+ // If we get here, it's ok to display this level...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_TeamOptions
+//
+// PURPOSE: Does the NET_OPTIONS_TEAMS dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_TeamOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ ForceActiveFocus(hDlg);
+ NetStart_InitTeamOptions(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillTeamOptions(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+
+BOOL NetStart_InitTeamOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Init the dialog controls...
+
+ CheckDlgButton(hDlg, IDC_FRIENDLYFIRE, s_bFriendlyFire ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_NEGFRAGS, s_bNegTeamFrags ? BST_CHECKED : BST_UNCHECKED);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillTeamOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Read the dialog controls...
+
+ s_bFriendlyFire = IsDlgButtonChecked(hDlg, IDC_FRIENDLYFIRE) == BST_CHECKED;
+ s_bNegTeamFrags = IsDlgButtonChecked(hDlg, IDC_NEGFRAGS) == BST_CHECKED;
+
+
+ // Update the game strucutre...
+
+ s_pNetGame->m_bFriendlyFire = s_bFriendlyFire;
+ s_pNetGame->m_bNegTeamFrags = s_bNegTeamFrags;
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_CtfOptions
+//
+// PURPOSE: Does the NET_OPTIONS_CTF dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_CtfOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ ForceActiveFocus(hDlg);
+ NetStart_InitCtfOptions(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillCtfOptions(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+BOOL NetStart_InitCtfOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Init the dialog controls...
+
+ CheckDlgButton(hDlg, IDC_FRIENDLYFIRE, s_bFriendlyFire ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_NEGFRAGS, s_bNegTeamFrags ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hDlg, IDC_ONLYFLAGSCORES, s_bOnlyFlagScores ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_USETEAMSIZE, s_bUseTeamSize ? BST_CHECKED : BST_UNCHECKED);
+
+ SetDlgItemInt(hDlg, IDC_FLAGVALUE, s_nFlagValue, FALSE);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillCtfOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Read the dialog controls...
+
+ s_bFriendlyFire = IsDlgButtonChecked(hDlg, IDC_FRIENDLYFIRE) == BST_CHECKED;
+ s_bNegTeamFrags = IsDlgButtonChecked(hDlg, IDC_NEGFRAGS) == BST_CHECKED;
+
+ s_bOnlyFlagScores = IsDlgButtonChecked(hDlg, IDC_ONLYFLAGSCORES) == BST_CHECKED;
+ s_bUseTeamSize = IsDlgButtonChecked(hDlg, IDC_USETEAMSIZE) == BST_CHECKED;
+
+ s_nFlagValue = GetDlgItemInt(hDlg, IDC_FLAGVALUE, NULL, FALSE);
+
+
+ // Update the game strucutre...
+
+ s_pNetGame->m_bFriendlyFire = s_bFriendlyFire;
+ s_pNetGame->m_bNegTeamFrags = s_bNegTeamFrags;
+ s_pNetGame->m_bOnlyFlagScores = s_bOnlyFlagScores;
+ s_pNetGame->m_bUseTeamSize = s_bUseTeamSize;
+ s_pNetGame->m_nFlagValue = s_nFlagValue;
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: NetStart_SoccerOptions
+//
+// PURPOSE: Does the NET_OPTIONS_SOCCER dialog
+//
+// ----------------------------------------------------------------------- //
+
+BOOL CALLBACK NetDlg_SoccerOptions(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ ForceActiveFocus(hDlg);
+ NetStart_InitSoccerOptions(hDlg);
+ return(TRUE);
+ }
+
+ case WM_COMMAND:
+ {
+ if (NetStart_HandleDefaultDialogCommands(hDlg, wParam))
+ {
+ return(TRUE);
+ }
+ else if (wParam == IDC_NEXT)
+ {
+ NetStart_FillSoccerOptions(hDlg);
+ EndDialog(hDlg, DLG_NEXT);
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+BOOL NetStart_InitSoccerOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Init the dialog controls...
+
+ CheckDlgButton(hDlg, IDC_FRIENDLYFIRE, s_bFriendlyFire ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_NEGFRAGS, s_bNegTeamFrags ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hDlg, IDC_ONLYGOALSCORES, s_bOnlyGoalScores ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_USETEAMSIZE, s_bUseTeamSize ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hDlg, IDC_SKIN_SOCCER, (s_nSocBallSkin == SOCBALL_SKIN_SOCCER) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_SKIN_ZOMBIE, (s_nSocBallSkin == SOCBALL_SKIN_ZOMBIE) ? BST_CHECKED : BST_UNCHECKED);
+
+ SetDlgItemInt(hDlg, IDC_GOALVALUE, s_nGoalValue, FALSE);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+BOOL NetStart_FillSoccerOptions(HWND hDlg)
+{
+ // Sanity checks...
+
+ if (!hDlg) return(FALSE);
+
+
+ // Read the dialog controls...
+
+ s_bFriendlyFire = IsDlgButtonChecked(hDlg, IDC_FRIENDLYFIRE) == BST_CHECKED;
+ s_bNegTeamFrags = IsDlgButtonChecked(hDlg, IDC_NEGFRAGS) == BST_CHECKED;
+
+ s_bOnlyGoalScores = IsDlgButtonChecked(hDlg, IDC_ONLYGOALSCORES) == BST_CHECKED;
+ s_bUseTeamSize = IsDlgButtonChecked(hDlg, IDC_USETEAMSIZE) == BST_CHECKED;
+
+ if (IsDlgButtonChecked(hDlg, IDC_SKIN_SOCCER) == BST_CHECKED) s_nSocBallSkin = SOCBALL_SKIN_SOCCER;
+ if (IsDlgButtonChecked(hDlg, IDC_SKIN_ZOMBIE) == BST_CHECKED) s_nSocBallSkin = SOCBALL_SKIN_ZOMBIE;
+
+ s_nGoalValue = GetDlgItemInt(hDlg, IDC_GOALVALUE, NULL, FALSE);
+
+
+ // Update the game strucutre...
+
+ s_pNetGame->m_bFriendlyFire = s_bFriendlyFire;
+ s_pNetGame->m_bNegTeamFrags = s_bNegTeamFrags;
+ s_pNetGame->m_bOnlyGoalScores = s_bOnlyFlagScores;
+ s_pNetGame->m_bUseTeamSize = s_bUseTeamSize;
+ s_pNetGame->m_nGoalValue = s_nFlagValue;
+ s_pNetGame->m_nSocBallSkin = s_nSocBallSkin;
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+
+
+
+
+
diff --git a/Blood2Serv/NetStart.h b/Blood2Serv/NetStart.h
new file mode 100644
index 0000000..6361056
--- /dev/null
+++ b/Blood2Serv/NetStart.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+;
+; MODULE: NetStart (.H)
+;
+; PURPOSE: Network game start/join/host dialog code
+;
+; HISTORY: 06/28/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+#ifndef _NETSTART_H_
+#define _NETSTART_H_
+
+
+// Includes...
+
+#include "netdefs.h"
+#include "server_interface.h"
+
+
+// Defines...
+
+#define NML_LEVEL 128 // NML: net max len
+
+#define NGT_SINGLE 0 // NGT: net game type
+#define NGT_DEATHMATCH 1
+#define NGT_CAPTUREFLAG 2
+#define NGT_COOPERATIVE 3
+
+#define NST_GAMENAME "NAME" // NST: net string token
+#define NST_GAMEHOST "HOST"
+#define NST_GAMETYPE "TYPE"
+#define NST_GAMELEVEL "LEVL"
+#define NST_GAMETIME "TIME"
+#define NST_PLRCOUNT "PLRS"
+#define NST_PLRNAME_BASE "PLRN"
+#define NST_PLRFRAG_BASE "PLRF"
+#define NST_CURLEVEL "CLEV"
+#define NST_NEXTLEVEL "NLEV"
+#define NST_GENERICMESSAGE "GMSG"
+#define NST_CONSOLEMSG "CMSG"
+
+#define NGE_FRAGS 1 // NGE: net game end
+#define NGE_TIME 2
+
+#define NGM_STANDARDUPDATE 0 // NGM: net generic message
+#define NGM_LEVELCHANGE 1
+#define NGM_CONSOLEMSG 2
+
+
+// Structures...
+
+typedef struct ServerInfo_t
+{
+ char m_sName[128];
+ char m_sService[128];
+ char m_sAddress[128];
+ DWORD m_dwMaxPlayers;
+ BOOL m_bUpdateGameInfo;
+ BOOL m_bRegisterServer;
+ BOOL m_bUseGameSpy;
+
+} ServerInfo;
+
+
+// Prototypes...
+void NetStart_LoadConsoleVars();
+void NetStart_SaveConsoleVars();
+BOOL NS_GetGameVar(char *pName, int &val);
+DRESULT NetStart_SaveConfigFile(char *pFilename);
+
+BOOL NetStart_DoWizard(HINSTANCE hInst, ServerInfo* pServerInfo, ServerOptions* pServerOptions, NetGame* pNetGame, BOOL bNoDlgs, char *pConfig);
+BOOL NetStart_GoNoDialogs(ServerInfo* pServerInfo, NetGame* pNetGame);
+BOOL NetStart_RunServerOptions(ServerInterface* pServerMgr, ServerOptions* pServerOptions);
+BOOL NetStart_DoOptionsDialog(HWND hWnd, ServerInterface* pServerMgr, ServerOptions* pServerOptions);
+
+int NetStart_GetPort();
+
+
+// EOF...
+
+#endif
+
+
+
diff --git a/Blood2Serv/Res/CoolServ.ico b/Blood2Serv/Res/CoolServ.ico
new file mode 100644
index 0000000..454a5b1
--- /dev/null
+++ b/Blood2Serv/Res/CoolServ.ico
Binary files differ
diff --git a/Blood2Serv/Res/CoolServ.rc2 b/Blood2Serv/Res/CoolServ.rc2
new file mode 100644
index 0000000..c744aab
--- /dev/null
+++ b/Blood2Serv/Res/CoolServ.rc2
@@ -0,0 +1,13 @@
+//
+// COOLSERV.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/Blood2Serv/Res/game1.bmp b/Blood2Serv/Res/game1.bmp
new file mode 100644
index 0000000..b367bf9
--- /dev/null
+++ b/Blood2Serv/Res/game1.bmp
Binary files differ
diff --git a/Blood2Serv/Res/vssver.scc b/Blood2Serv/Res/vssver.scc
new file mode 100644
index 0000000..ec28365
--- /dev/null
+++ b/Blood2Serv/Res/vssver.scc
Binary files differ
diff --git a/Blood2Serv/RezFind.cpp b/Blood2Serv/RezFind.cpp
new file mode 100644
index 0000000..9139fc1
--- /dev/null
+++ b/Blood2Serv/RezFind.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+;
+; MODULE: REZFIND (.CPP)
+;
+; PURPOSE: Routines to find the rez files
+;
+; HISTORY: 08/11/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+// Includes...
+
+#include "StdAfx.h"
+#include "Io.h"
+#include "RezFind.h"
+#include "Resource.h"
+
+
+// Globals...
+
+char g_sGameRez[128] = { "" };
+char g_sSoundRez[128] = { "" };
+
+
+// Prototypes...
+
+BOOL ExistRezFile(const char* sFile);
+BOOL ExistRezDir(const char* sDir);
+
+
+// Functions...
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: FindRezFiles
+//
+// PURPOSE: Looks for game and sound rez files
+//
+// ----------------------------------------------------------------------- //
+
+BOOL FindRezFiles(HINSTANCE hInst)
+{
+ // Sanity checks...
+
+ if (!hInst) return(FALSE);
+
+
+ // Clear the strings...
+
+ g_sGameRez[0] = '\0';
+ g_sSoundRez[0] = '\0';
+
+
+ // Load the rez file base name to use...
+
+ CString sGameRezBase;
+ CString sGameRezFile;
+ CString sGameRezDir;
+
+ if (!sGameRezBase.LoadString(IDS_REZBASE))
+ {
+ return(FALSE);
+ }
+
+ sGameRezFile = sGameRezBase + ".rez";
+ sGameRezDir = sGameRezBase;
+
+
+ // Look for game rez in the current directory...
+
+ if (ExistRezFile(sGameRezFile))
+ {
+ strcpy(g_sGameRez, sGameRezFile);
+ }
+
+
+ // If necessary, look for a shogo directory in the current directory...
+
+ if (g_sGameRez[0] == '\0')
+ {
+ if (ExistRezDir(sGameRezDir))
+ {
+ strcpy(g_sGameRez, sGameRezDir);
+ }
+ }
+
+
+ // Look for sound.rez in the current directory...
+
+ if (ExistRezFile("sound.rez"))
+ {
+ strcpy(g_sSoundRez, "sound.rez");
+ }
+
+
+ // If necessary, look for a sound directory...
+
+ if (g_sSoundRez[0] == '\0')
+ {
+ if (ExistRezDir("sound"))
+ {
+ strcpy(g_sSoundRez, "sound");
+ }
+ }
+
+
+ // Determine if we have enough rez info...
+
+ if (g_sGameRez[0] == '\0')
+ {
+ return(FALSE);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+char* GetGameRezFile()
+{
+ return(g_sGameRez);
+}
+
+char* GetSoundRezFile()
+{
+ return(g_sSoundRez);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: ExistRezFile
+//
+// PURPOSE: Determines if the given file exists
+//
+// ----------------------------------------------------------------------- //
+
+BOOL ExistRezFile(const char* sFile)
+{
+ // Sanity checks...
+
+ if (!sFile) return(FALSE);
+ if (sFile[0] == '\0') return(FALSE);
+
+
+ // Check if this file exists...
+
+ struct _finddata_t c_file;
+ long hFile;
+
+ hFile = _findfirst(sFile, &c_file);
+ if (hFile == -1L) return(FALSE);
+
+ if (c_file.attrib & _A_SUBDIR)
+ {
+ return(FALSE);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: ExistRezDir
+//
+// PURPOSE: Determines if the given directory exists
+//
+// ----------------------------------------------------------------------- //
+
+BOOL ExistRezDir(const char* sDir)
+{
+ // Sanity checks...
+
+ if (!sDir) return(FALSE);
+ if (sDir[0] == '\0') return(FALSE);
+
+
+ // Check if this directory exists...
+
+ struct _finddata_t c_file;
+ long hFile;
+
+ hFile = _findfirst(sDir, &c_file);
+ if (hFile == -1L) return(FALSE);
+
+ if (!(c_file.attrib & _A_SUBDIR))
+ {
+ return(FALSE);
+ }
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+
diff --git a/Blood2Serv/RezFind.h b/Blood2Serv/RezFind.h
new file mode 100644
index 0000000..aa1378d
--- /dev/null
+++ b/Blood2Serv/RezFind.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+;
+; MODULE: REZFIND (.H)
+;
+; PURPOSE: Routines to find the rez files
+;
+; HISTORY: 08/11/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+#ifndef _REZFIND_H_
+#define _REZFIND_H_
+
+
+// Prototypes...
+
+BOOL FindRezFiles(HINSTANCE hInst);
+char* GetGameRezFile();
+char* GetSoundRezFile();
+
+
+// EOF
+
+#endif
diff --git a/Blood2Serv/ServerUtils.cpp b/Blood2Serv/ServerUtils.cpp
new file mode 100644
index 0000000..b9fd9ba
--- /dev/null
+++ b/Blood2Serv/ServerUtils.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+;
+; MODULE: ServerUtils (.CPP)
+;
+; PURPOSE: Server Utility Functions
+;
+; HISTORY: 08/04/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+// Includes...
+
+#include "StdAfx.h"
+#include "ServerUtils.h"
+#include "WinInet.h"
+
+
+// Externs...
+
+extern CString g_sWebRegUrl;
+extern DGUID GAMEGUID;
+
+
+// Globals...
+
+HINSTANCE s_hServerDLL = NULL;
+CreateServerFn s_fnCreateServer = NULL;
+DeleteServerFn s_fnDeleteServer = NULL;
+ServerInterface* s_pServerMgr = NULL;
+
+
+// Functions...
+
+BOOL LoadServerDLL(char *pDLLName)
+{
+ SI_CREATESTATUS status;
+
+ if (s_pServerMgr && s_hServerDLL)
+ {
+ return(TRUE);
+ }
+
+ s_hServerDLL = LoadLibrary(pDLLName);
+
+ if(!s_hServerDLL)
+ {
+ return(FALSE);
+ }
+
+ s_fnCreateServer = (CreateServerFn)GetProcAddress(s_hServerDLL, "CreateServer");
+ s_fnDeleteServer = (DeleteServerFn)GetProcAddress(s_hServerDLL, "DeleteServer");
+
+ if (!s_fnCreateServer || !s_fnDeleteServer)
+ {
+ FreeLibrary(s_hServerDLL);
+ s_hServerDLL = NULL;
+ return(NULL);
+ }
+
+ s_pServerMgr = NULL;
+
+ status = s_fnCreateServer(SI_VERSION, GAMEGUID, &s_pServerMgr);
+
+ if (status != 0)
+ {
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+ServerInterface* GetServerInterface()
+{
+ return(s_pServerMgr);
+}
+
+void FreeServerDLL()
+{
+ if (s_hServerDLL && s_fnDeleteServer)
+ {
+ s_fnDeleteServer();
+ FreeLibrary(s_hServerDLL);
+ }
+
+ s_hServerDLL = NULL;
+ s_fnCreateServer = NULL;
+ s_fnDeleteServer = NULL;
+ s_pServerMgr = NULL;
+}
+
+BOOL SendWebInfo2(const char* sSite, const char* sInfo, BOOL bWait)
+{
+ // Sanity checks...
+
+ if (!sSite) return(FALSE);
+ if (!sInfo) return(FALSE);
+
+
+ // Open the internet and get a handle to it...
+
+ HINTERNET hNet = InternetOpen("GameServ", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
+ if (!hNet) return(FALSE);
+
+
+ // Create the URL we want from the given parameters...
+
+ CString sUrl(sSite);
+
+ sUrl += "?";
+ sUrl += sInfo;
+
+
+ // Convert spaces to pluses...
+
+ int nLen = sUrl.GetLength();
+
+ for (int i = 0; i < nLen; i++)
+ {
+ if (sUrl.GetAt(i) == ' ') sUrl.SetAt(i, '+');
+ }
+
+
+ // Open the URL we want...
+
+ HINTERNET hHttp = InternetOpenUrl(hNet, sUrl, NULL, 0, 0, 0);
+ if (!hHttp)
+ {
+ InternetCloseHandle(hNet);
+ return(FALSE);
+ }
+
+
+ // Wait until the request is finished...
+
+ if (bWait)
+ {
+ DWORD dwSize = 0;
+ char sBuf[1024];
+
+ strcpy(sBuf, "");
+
+ if (!InternetReadFile(hHttp, sBuf, 1000, &dwSize))
+ {
+ InternetCloseHandle(hNet);
+ return(FALSE);
+ }
+ }
+
+
+ // Clean up...
+
+ InternetCloseHandle(hNet);
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+void RemoveTrailingStuff(char *pStr)
+{
+ int len;
+
+ len = strlen(pStr);
+ if(len > 0 && pStr[len-1] == '\n')
+ {
+ pStr[len-1] = 0;
+ }
+}
+
+BOOL SendWebInfo(const char* sInfo, BOOL bWait)
+{
+ char site[256];
+ FILE *fp;
+
+ SendWebInfo2(g_sWebRegUrl, sInfo, bWait);
+
+ // Ignore sSite and get it from the file.
+ if(!(fp = fopen("srv_send.txt", "rt")))
+ return FALSE;
+
+ while(fgets(site, sizeof(site), fp))
+ {
+ RemoveTrailingStuff(site);
+ SendWebInfo2(site, sInfo, bWait);
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+
+
diff --git a/Blood2Serv/ServerUtils.h b/Blood2Serv/ServerUtils.h
new file mode 100644
index 0000000..51f0322
--- /dev/null
+++ b/Blood2Serv/ServerUtils.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+;
+; MODULE: ServerUtils (.H)
+;
+; PURPOSE: Server Utility Functions
+;
+; HISTORY: 08/04/98 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1998, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+#ifndef _SERVERUTILS_H_
+#define _SERVERUTILS_H_
+
+
+// Includes...
+
+#include "server_interface.h"
+
+
+// Prototypes...
+
+BOOL LoadServerDLL(char *pDLLName);
+ServerInterface* GetServerInterface();
+void FreeServerDLL();
+BOOL SendWebInfo(const char* sInfo, BOOL bWait);
+
+
+// EOF...
+
+#endif
+
+
diff --git a/Blood2Serv/Sparam.cpp b/Blood2Serv/Sparam.cpp
new file mode 100644
index 0000000..3836da6
--- /dev/null
+++ b/Blood2Serv/Sparam.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+;
+; MODULE: SPARAM (.CPP)
+;
+; PURPOSE: String Parameter funcions
+;
+; HISTORY: 10/13/96 [blg] This file was created
+;
+; COMMENT: Copyright (c) 1996, Monolith Productions Inc.
+;
+****************************************************************************/
+
+
+// Includes...
+
+#include "StdAfx.h"
+#include "Sparam.h"
+
+
+// Functions...
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: Sparam_Get
+//
+// PURPOSE: Gets the parameter with the given ID
+//
+// ----------------------------------------------------------------------- //
+
+BOOL Sparam_Get(char* sDest, const char* sSource, const char* sId)
+{
+ // Sanity checks...
+
+ ASSERT(sSource);
+ ASSERT(sId);
+
+
+ // Scan for the ID...
+
+ char sRealId[256];
+ wsprintf(sRealId, "[%s:", sId);
+
+ char* sStart = strstr(sSource, sRealId);
+ if (!sStart) return(FALSE);
+
+
+ // Move to the start of the param...
+
+ int nLen = strlen(sRealId);
+ sStart = &sStart[nLen];
+ if (strlen(sStart) < 2) return(FALSE);
+
+
+ // Find the end of the param...
+
+ char* pEnd = strstr(sStart, "]");
+ if (!pEnd) return(FALSE);
+ if (pEnd <= sStart) return(FALSE);
+
+
+ // Fill the dest string with the param...
+
+ int i = 0;
+
+ while (&sStart[i] != pEnd)
+ {
+ sDest[i] = sStart[i];
+ i++;
+ }
+
+ sDest[i] = '\0';
+
+
+ // All done...
+
+ return(TRUE);
+}
+
+
+// ----------------------------------------------------------------------- //
+//
+// ROUTINE: Sparam_Add
+//
+// PURPOSE: Addss the given parameter with the given ID
+//
+// WARNING: The source string must contain enough extra memory for
+//