1 /*
2  * Copyright 2011-2013 Arx Libertatis Team (see the AUTHORS file)
3  *
4  * This file is part of Arx Libertatis.
5  *
6  * Arx Libertatis is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Arx Libertatis is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Arx Libertatis.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23 
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25 
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28 
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31 
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code.  If not, see
33 <http://www.gnu.org/licenses/>.
34 
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38 
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43 // Code: Cyril Meynier
44 //
45 // Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
46 
47 #include "core/Core.h"
48 
49 #include <cstdlib>
50 #include <cstring>
51 #include <cstdio>
52 #include <algorithm>
53 #include <sstream>
54 #include <vector>
55 
56 #include <boost/version.hpp>
57 #include <boost/foreach.hpp>
58 
59 #include "Configure.h"
60 
61 #include "ai/Paths.h"
62 #include "ai/PathFinderManager.h"
63 
64 #include "animation/Animation.h"
65 #include "animation/Cinematic.h"
66 #include "animation/CinematicKeyframer.h"
67 
68 #include "core/Application.h"
69 #include "core/ArxGame.h"
70 #include "core/Config.h"
71 #include "core/Localisation.h"
72 #include "core/GameTime.h"
73 #include "core/Version.h"
74 
75 #include "game/Damage.h"
76 #include "game/EntityManager.h"
77 #include "game/Equipment.h"
78 #include "game/Inventory.h"
79 #include "game/Levels.h"
80 #include "game/Missile.h"
81 #include "game/NPC.h"
82 #include "game/Player.h"
83 #include "game/Spells.h"
84 
85 #include "gui/MenuPublic.h"
86 #include "gui/Menu.h"
87 #include "gui/MenuWidgets.h"
88 #include "gui/Speech.h"
89 #include "gui/MiniMap.h"
90 #include "gui/TextManager.h"
91 
92 #include "graphics/BaseGraphicsTypes.h"
93 #include "graphics/Draw.h"
94 #include "graphics/font/Font.h"
95 #include "graphics/GraphicsModes.h"
96 #include "graphics/GraphicsTypes.h"
97 #include "graphics/Math.h"
98 #include "graphics/Renderer.h"
99 #include "graphics/Vertex.h"
100 #include "graphics/data/FTL.h"
101 #include "graphics/data/TextureContainer.h"
102 #include "graphics/effects/Fog.h"
103 #include "graphics/image/Image.h"
104 #include "graphics/particle/ParticleEffects.h"
105 #include "graphics/particle/ParticleManager.h"
106 #include "graphics/texture/TextureStage.h"
107 
108 #include "gui/Interface.h"
109 #include "gui/Text.h"
110 
111 #include "input/Input.h"
112 #include "input/Keyboard.h"
113 #include "input/Mouse.h"
114 
115 #include "io/fs/SystemPaths.h"
116 #include "io/resource/ResourcePath.h"
117 #include "io/resource/PakReader.h"
118 #include "io/CinematicLoad.h"
119 #include "io/Screenshot.h"
120 #include "io/log/Logger.h"
121 
122 #include "math/Angle.h"
123 #include "math/Rectangle.h"
124 #include "math/Vector2.h"
125 #include "math/Vector3.h"
126 
127 #include "physics/Collisions.h"
128 #include "physics/Attractors.h"
129 
130 #include "platform/CrashHandler.h"
131 #include "platform/Flags.h"
132 #include "platform/Platform.h"
133 
134 #include "scene/LinkedObject.h"
135 #include "scene/CinematicSound.h"
136 #include "scene/ChangeLevel.h"
137 #include "scene/Scene.h"
138 #include "scene/GameSound.h"
139 #include "scene/LoadLevel.h"
140 #include "scene/Interactive.h"
141 #include "scene/Light.h"
142 #include "scene/Object.h"
143 
144 #include "script/Script.h"
145 #include "script/ScriptEvent.h"
146 
147 #include "window/RenderWindow.h"
148 
149 class TextManager;
150 
151 using std::min;
152 using std::max;
153 using std::string;
154 using std::ostringstream;
155 
156 Image savegame_thumbnail;
157 
158 #define MAX_EXPLO 24
159 
160 static bool initializeGame();
161 static void shutdownGame();
162 
163 extern TextManager	*pTextManage;
164 extern float FORCE_TIME_RESTORE;
165 extern CMenuState		*pMenu;
166 extern Entity * CURRENT_TORCH;
167 extern EERIE_3DOBJ * fogobj;
168 extern float	InventoryX;
169 extern float	PROGRESS_BAR_COUNT;
170 extern float	PROGRESS_BAR_TOTAL;
171 extern float	vdist;
172 extern long		FistParticles;
173 extern long		INTER_DRAW;
174 extern long		DONT_WANT_PLAYER_INZONE;
175 extern long		TOTPDL;
176 extern long		COLLIDED_CLIMB_POLY;
177 extern long LastSelectedIONum;
178 extern float ARXTimeMenu;
179 extern float ARXOldTimeMenu;
180 extern long		REFUSE_GAME_RETURN;
181 extern bool		PLAYER_MOUSELOOK_ON;
182 extern long		FRAME_COUNT;
183 extern bool bFadeInOut;
184 extern 	bool bFade;			//active le fade
185 extern float OLD_PROGRESS_BAR_COUNT;
186 #ifdef BUILD_EDITOR
187 long LastSelectedIONum = -1;
188 #endif
189 
190 extern EERIE_3DOBJ * ssol;
191 extern long ssol_count;
192 extern EERIE_3DOBJ * slight;
193 extern long slight_count;
194 extern EERIE_3DOBJ * srune;
195 extern long srune_count;
196 extern EERIE_3DOBJ * smotte;
197 extern long smotte_count;
198 extern EERIE_3DOBJ * stite;
199 extern long stite_count;
200 extern EERIE_3DOBJ * smissile;
201 extern long smissile_count;
202 extern EERIE_3DOBJ * spapi;
203 extern long spapi_count;
204 extern EERIE_3DOBJ * svoodoo;
205 extern long svoodoo_count;
206 
207 //-----------------------------------------------------------------------------
208 // Our Main Danae Application.& Instance and Project
209 PROJECT Project;
210 
211 //-----------------------------------------------------------------------------
212 Vec3f PUSH_PLAYER_FORCE;
213 Cinematic			*ControlCinematique=NULL;	// 2D Cinematic Controller
214 ParticleManager	*pParticleManager = NULL;
215 static TextureContainer * ombrignon = NULL;
216 static TextureContainer *  Flying_Eye = NULL;
217 TextureContainer *	scursor[8];			// Animated Hand Cursor TC
218 TextureContainer *	pTCCrossHair;			// Animated Hand Cursor TC
219 TextureContainer *	iconequip[5];
220 TextureContainer *	GoldCoinsTC[MAX_GOLD_COINS_VISUALS]; // Gold Coins Icons
221 TextureContainer *	explo[MAX_EXPLO];		// TextureContainer for animated explosion bitmaps (24 frames)
222 TextureContainer *	blood_splat = NULL;		// TextureContainer for blood splat particles
223 
224 TextureContainer *	tflare = NULL;
225 static TextureContainer * npc_fight = NULL;
226 static TextureContainer * npc_follow = NULL;
227 static TextureContainer * npc_stop = NULL;
228 TextureContainer *	sphere_particle=NULL;
229 TextureContainer *	inventory_font=NULL;
230 TextureContainer *	enviro=NULL;
231 TextureContainer *	specular=NULL;
232 TextureContainer *	lightsource_tc=NULL;
233 TextureContainer *	stealth_gauge_tc=NULL;
234 TextureContainer *	arx_logo_tc=NULL;
235 TextureContainer *	TC_fire2=NULL;
236 TextureContainer *	TC_fire=NULL;
237 TextureContainer *	TC_smoke=NULL;
238 static TextureContainer *	Z_map = NULL;
239 TextureContainer *	Boom=NULL;
240 //TextureContainer *	zbtex=NULL;
241 TextureContainer *	mecanism_tc=NULL;
242 TextureContainer *	arrow_left_tc=NULL;
243 
244 #ifdef BUILD_EDIT_LOADSAVE
245 extern long NEED_ANCHORS;
246 EERIE_MULTI3DSCENE * mse = NULL;
247 long ADDED_IO_NOT_SAVED = 0;
248 #endif
249 
250 SPELL_ICON spellicons[SPELL_COUNT];
251 bool bGToggleCombatModeWithKey;
252 
253 Vec2s DANAEMouse;
254 Vec3f moveto;
255 Vec3f Mscenepos;
256 Vec3f lastteleport;
257 EERIE_3DOBJ * GoldCoinsObj[MAX_GOLD_COINS_VISUALS];// 3D Objects For Gold Coins
258 EERIE_3DOBJ	* arrowobj=NULL;			// 3D Object for arrows
259 EERIE_3DOBJ * cameraobj=NULL;			// Camera 3D Object		// NEEDTO: Remove for Final
260 EERIE_3DOBJ * markerobj=NULL;			// Marker 3D Object		// NEEDTO: Remove for Final
261 EERIE_3DOBJ * nodeobj=NULL;				// Node 3D Object		// NEEDTO: Remove for Final
262 EERIE_3DOBJ * eyeballobj=NULL;			// EyeBall 3D Object	// NEEDTO: Load dynamically
263 EERIE_3DOBJ * cabal=NULL;				// Cabalistic 3D Object // NEEDTO: Load dynamically
264 static EERIE_BACKGROUND DefaultBkg;
265 EERIE_CAMERA TCAM[32];
266 EERIE_CAMERA subj,mapcam,bookcam,raycam,conversationcamera;
267 
268 string WILLADDSPEECH;
269 
270 Vec2s STARTDRAG;
271 Entity * COMBINE=NULL;
272 
273 QUAKE_FX_STRUCT QuakeFx;
274 string LAST_FAILED_SEQUENCE = "none";
275 // START - Information for Player Teleport between/in Levels-------------------------------------
276 char TELEPORT_TO_LEVEL[64];
277 char TELEPORT_TO_POSITION[64];
278 long TELEPORT_TO_ANGLE;
279 // END -   Information for Player Teleport between/in Levels---------------------------------------
280 std::string WILL_LAUNCH_CINE;
281 res::path LastLoadedScene;
282 static std::string LAST_LAUNCHED_CINE;
283 float BASE_FOCAL=350.f;
284 float STRIKE_AIMTIME=0.f;
285 float SLID_VALUE=0.f;
286 float framedelay;
287 
288 static float LASTfps2 = 0;
289 static float fps2 = 0;
290 static float fps2min = 0;
291 static long LASTfpscount = 0;
292 
293 long LOAD_N_DONT_ERASE=0;
294 long NO_TIME_INIT=0;
295 long DANAESIZX=640;
296 long DANAESIZY=480;
297 long DANAECENTERX;
298 long DANAECENTERY;
299 long CurrFightPos=0;
300 long NO_PLAYER_POSITION_RESET=0;
301 long CURRENT_BASE_FOCAL=310;
302 long CINE_PRELOAD=0;
303 long PLAY_LOADED_CINEMATIC=0;
304 float BOW_FOCAL=0;
305 long PlayerWeaponBlocked=-1;
306 long SHOW_TORCH=0;
307 float FrameDiff=0;
308 float GLOBAL_LIGHT_FACTOR=0.85f;
309 
310 long USE_LIGHT_OPTIM	=1;
311 long STRIKE_TIME		= 0;
312 long STOP_KEYBOARD_INPUT= 0;
313 long REQUEST_SPEECH_SKIP= 0;
314 long CURRENTLEVEL		= -1;
315 long DONT_ERASE_PLAYER	= 0;
316 static float LastFrameTicks = 0;
317 long SPLASH_THINGS_STAGE= 0;
318 long STARTED_A_GAME		= 0;
319 long FASTmse			= 0;
320 
321 //-----------------------------------------------------------------------------
322 // EDITOR FLAGS/Vars
323 //-----------------------------------------------------------------------------
324 // Flag used to Launch Moulinex
325 long LOADEDD = 0; // Is a Level Loaded ?
326 #ifdef BUILD_EDITOR
327 long EDITMODE = 0; // EditMode (1) or GameMode (0) ?
328 long EDITION=EDITION_IO; // Sub-EditMode
329 long DEBUGNPCMOVE = 0; // Debug NPC Movements
330 #endif
331 
332 long CHANGE_LEVEL_ICON=-1;
333 
334 long ARX_MOUSE_OVER=0;
335 //-----------------------------------------------------------------------------
336 // DEBUG FLAGS/Vars
337 //-----------------------------------------------------------------------------
338 long LaunchDemo=0;
339 long FirstFrame=1;
340 unsigned long WILLADDSPEECHTIME=0;
341 unsigned long AimTime;
342 static unsigned long SPLASH_START = 0;
343 //-----------------------------------------------------------------------------
344 Color3f FADECOLOR;
345 
346 long START_NEW_QUEST=0;
347 static long LAST_WEAPON_TYPE = -1;
348 long	FADEDURATION=0;
349 long	FADEDIR=0;
350 unsigned long FADESTART=0;
351 
352 float Original_framedelay=0.f;
353 
354 float PULSATE;
355 long EXITING=0;
356 
357 long USE_PORTALS = 3;
358 
359 Vec3f ePos;
360 extern EERIE_CAMERA * ACTIVECAM;
361 
362 EERIE_CAMERA  * Kam;
363 
364 //-----------------------------------------------------------------------------
365 
366 void LoadSysTextures();
367 void ShowFPS();
368 void ManageNONCombatModeAnimations();
369 
370 //-----------------------------------------------------------------------------
371 
372 
373 // Sends ON GAME_READY msg to all IOs
SendGameReadyMsg()374 void SendGameReadyMsg()
375 {
376 	LogDebug("SendGameReadyMsg");
377 	SendMsgToAllIO(SM_GAME_READY);
378 }
379 
DANAE_KillCinematic()380 void DANAE_KillCinematic()
381 {
382 	if (	(ControlCinematique)
383 		&&	(ControlCinematique->projectload)	)
384 	{
385 		ControlCinematique->projectload=false;
386 		ControlCinematique->OneTimeSceneReInit();
387 		ControlCinematique->DeleteDeviceObjects();
388 		PLAY_LOADED_CINEMATIC=0;
389 		CINE_PRELOAD=0;
390 	}
391 }
392 
AdjustUI()393 static bool AdjustUI() {
394 
395 	// Sets Danae Screen size depending on windowed/full-screen state
396 	DANAESIZX = mainApp->GetWindow()->getSize().x;
397 	DANAESIZY = mainApp->GetWindow()->getSize().y;
398 
399 	// Now computes screen center
400 	DANAECENTERX = DANAESIZX>>1;
401 	DANAECENTERY = DANAESIZY>>1;
402 
403 	// Computes X & Y screen ratios compared to a standard 640x480 screen
404 	Xratio = DANAESIZX * ( 1.0f / 640 );
405 	Yratio = DANAESIZY * ( 1.0f / 480 );
406 
407 	if(!ARX_Text_Init()) {
408 		return false;
409 	}
410 
411 	if(pMenu) {
412 		pMenu->bReInitAll=true;
413 	}
414 
415 	return true;
416 }
417 
DanaeRestoreFullScreen()418 void DanaeRestoreFullScreen() {
419 
420 	if(pMenu) {
421 		pMenu->bReInitAll=true;
422 	}
423 
424 	AdjustUI();
425 
426 	LoadScreen();
427 }
428 
429 extern void InitTileLights();
430 
431 enum LevelNumber {
432 	LEVEL0     = 0,
433 	LEVEL1     = 1,
434 	LEVEL2     = 2,
435 	LEVEL3     = 3,
436 	LEVEL4     = 4,
437 	LEVEL5     = 5,
438 	LEVEL6     = 6,
439 	LEVEL7     = 7,
440 	LEVEL8     = 8,
441 	LEVEL9     = 9,
442 	LEVEL10    = 10,
443 	LEVEL11    = 11,
444 	LEVEL12    = 12,
445 	LEVEL13    = 13,
446 	LEVEL14    = 14,
447 	LEVEL15    = 15,
448 	LEVEL16    = 16,
449 	LEVEL17    = 17,
450 	LEVEL18    = 18,
451 	LEVEL19    = 19,
452 	LEVEL20    = 20,
453 	LEVEL21    = 21,
454 	LEVEL22    = 22,
455 	LEVEL23    = 23,
456 	LEVEL24    = 24,
457 	LEVEL25    = 25,
458 	LEVEL26    = 26,
459 	LEVEL27    = 27,
460 	LEVELDEMO  = 28,
461 	LEVELDEMO2 = 29,
462 	LEVELDEMO3 = 30,
463 	LEVELDEMO4 = 31,
464 	NOLEVEL    = 32
465 };
466 
InitializeDanae()467 void InitializeDanae() {
468 
469 	InitTileLights();
470 
471 	ARX_MISSILES_ClearAll();
472 	ARX_SPELLS_Init();
473 
474 	ARX_SPELLS_ClearAllSymbolDraw();
475 	ARX_PARTICLES_ClearAll();
476 	ARX_MAGICAL_FLARES_FirstInit();
477 
478 	LastLoadedScene.clear();
479 
480 	res::path levelPath;
481 	res::path levelFullPath;
482 
483 	if(Project.demo != NOLEVEL) {
484 		char levelId[256];
485 		GetLevelNameByNum(Project.demo, levelId);
486 		levelPath = std::string("graph/levels/level") + levelId;
487 		levelFullPath = levelPath.string() + "/level" + levelId + ".dlf";
488 	}
489 
490 	memset(&DefaultBkg, 0, sizeof(EERIE_BACKGROUND));
491 	ACTIVEBKG=&DefaultBkg;
492 	InitBkg(ACTIVEBKG,MAX_BKGX,MAX_BKGZ,BKG_SIZX,BKG_SIZZ);
493 	InitNodes(1);
494 
495 	player.size.y = subj.size.a = -player.baseHeight();
496 	player.size.x = subj.size.b = player.baseRadius();
497 	player.size.z = subj.size.g = player.baseRadius();
498 	player.desiredangle = player.angle = subj.angle = Anglef(3.f, 268.f, 0.f);
499 	subj.pos = Vec3f(900.f, player.baseHeight(), 4340.f);
500 	subj.clip = Rect(0, 0, 640, 480);
501 	subj.clipz0 = 0.f;
502 	subj.clipz1 = 2.999f;
503 	subj.center = subj.clip.center();
504 	subj.focal = BASE_FOCAL;
505 	subj.Zdiv = 3000.f;
506 	subj.Zmul = 1.f / subj.Zdiv;
507 	subj.clip3D = 60;
508 	subj.type = CAM_SUBJVIEW;
509 	subj.bkgcolor = Color::none;
510 
511 	SetActiveCamera(&subj);
512 	SetCameraDepth(2100.f);
513 	memcpy(&bookcam, &subj, sizeof(EERIE_CAMERA));
514 	memcpy(&raycam, &subj, sizeof(EERIE_CAMERA));
515 	memcpy(&conversationcamera, &subj, sizeof(EERIE_CAMERA));
516 
517 	raycam.center = Vec2i(320, 320);
518 
519 	bookcam.angle = Anglef::ZERO;
520 	bookcam.pos = Vec3f::ZERO;
521 	bookcam.focal = BASE_FOCAL;
522 
523 	// TODO probably not really used anymore!
524 	mapcam.pos = Vec3f(1500.f, -6000.f, 1500.f);
525 	mapcam.angle = Anglef(90.f, 0.f, 0.f);
526 	mapcam.clip = Rect(0, 0, 640, 480);
527 	mapcam.clipz0 = 0.001f;
528 	mapcam.clipz1 = 0.999f;
529 	mapcam.center = mapcam.clip.center();
530 	mapcam.focal = 400.f;
531 	mapcam.Zdiv = 3000.f;
532 	mapcam.Zmul = 1.f / mapcam.Zdiv;
533 	mapcam.clip3D = 1000;
534 	mapcam.type = CAM_TOPVIEW;
535 	mapcam.bkgcolor = Color::fromBGRA(0x001F1F55);
536 	SetActiveCamera(&mapcam);
537 	SetCameraDepth(10000.f);
538 
539 	for(size_t i = 0; i < 32; i++) {
540 		memcpy(&TCAM[i],&subj,sizeof(EERIE_CAMERA));
541 	}
542 
543 	ACTIVEBKG->ambient = Color3f(0.09f, 0.09f, 0.09f);
544 	ACTIVEBKG->ambient255 = ACTIVEBKG->ambient * 255.f;
545 
546 	LoadSysTextures();
547 	CreateInterfaceTextureContainers();
548 
549 	if(LaunchDemo) {
550 		LogInfo << "Launching splash screens.";
551 		LaunchDemo = 0;
552 		SPLASH_THINGS_STAGE = 11;
553 	} else if(!levelPath.empty())	{
554 		LogInfo << "Launching Level " << levelPath;
555 		if (FastSceneLoad(levelPath)) {
556 			FASTmse = 1;
557 		} else {
558 #ifdef BUILD_EDIT_LOADSAVE
559 			ARX_SOUND_PlayCinematic("editor_humiliation", false);
560 			mse = PAK_MultiSceneToEerie(levelPath);
561 #else
562 			LogError << "FastSceneLoad failed";
563 #endif
564 		}
565 		EERIEPOLY_Compute_PolyIn();
566 		LastLoadedScene = levelPath;
567 		USE_PLAYERCOLLISIONS=0;
568 	}
569 }
570 
initializeGame()571 static bool initializeGame() {
572 
573 	// TODO Time will be re-initialized later, but if we don't initialize it now casts to int might overflow.
574 	arxtime.init();
575 
576 	mainApp = new ArxGame();
577 	if(!mainApp->Initialize()) {
578 		// Fallback to a generic critical error in case none was set yet...
579 		LogCritical << "Application failed to initialize properly.";
580 		return false;
581 	}
582 
583 	// Check if the game will be able to use the current game directory.
584 	if(!ARX_Changelevel_CurGame_Clear()) {
585 		LogCritical << "Error accessing current game directory.";
586 		return false;
587 	}
588 
589 	ScriptEvent::init();
590 
591 	CalcFPS(true);
592 
593 	g_miniMap.mapMarkerInit();
594 
595 	memset(scursor, 0, sizeof(scursor));
596 
597 	ARX_SPELLS_CancelSpellTarget();
598 
599 	memset(explo, 0, sizeof(explo));
600 
601 	LogDebug("Danae Start");
602 
603 	LogDebug("Project Init");
604 
605 	PUSH_PLAYER_FORCE = Vec3f::ZERO;
606 	ARX_SPECIAL_ATTRACTORS_Reset();
607 	LogDebug("Attractors Init");
608 	ARX_SPELLS_Precast_Reset();
609 	LogDebug("Spell Init");
610 
611 	for(size_t t = 0; t < MAX_GOLD_COINS_VISUALS; t++) {
612 		GoldCoinsObj[t] = NULL;
613 		GoldCoinsTC[t] = NULL;
614 	}
615 
616 	LogDebug("LSV Init");
617 	ModeLight=MODE_DYNAMICLIGHT | MODE_DEPTHCUEING;
618 
619 	memset(&DefaultBkg,0,sizeof(EERIE_BACKGROUND));
620 	memset(TELEPORT_TO_LEVEL,0,64);
621 	memset(TELEPORT_TO_POSITION,0,64);
622 	LogDebug("Mset");
623 
624 	LogDebug("AnimManager Init");
625 	ARX_SCRIPT_EventStackInit();
626 	LogDebug("EventStack Init");
627 	ARX_EQUIPMENT_Init();
628 	LogDebug("AEQ Init");
629 
630 	ARX_SCRIPT_Timer_FirstInit(512);
631 	LogDebug("Timer Init");
632 	ARX_FOGS_FirstInit();
633 	LogDebug("Fogs Init");
634 
635 	EERIE_LIGHT_GlobalInit();
636 	LogDebug("Lights Init");
637 
638 	LogDebug("Svars Init");
639 
640 	// Script Test
641 	lastteleport = player.baseOffset();
642 
643 	entities.init();
644 
645 	memset(&player,0,sizeof(ARXCHARACTER));
646 	ARX_PLAYER_InitPlayer();
647 
648 	CleanInventory();
649 
650 	ARX_SPEECH_FirstInit();
651 	ARX_CONVERSATION_FirstInit();
652 	ARX_SPEECH_Init();
653 	ARX_SPEECH_ClearAll();
654 	QuakeFx.intensity=0.f;
655 
656 	LogDebug("Launching DANAE");
657 
658 	memset(&Project, 0, sizeof(PROJECT));
659 
660 	LaunchDemo = 1;
661 	Project.demo = LEVEL10;
662 
663 	if(!AdjustUI()) {
664 		return false;
665 	}
666 
667 	ARX_SetAntiAliasing();
668 	ARXMenu_Options_Video_SetFogDistance(config.video.fogDistance);
669 	ARXMenu_Options_Video_SetDetailsQuality(config.video.levelOfDetail);
670 	ARXMenu_Options_Audio_SetMasterVolume(config.audio.volume);
671 	ARXMenu_Options_Audio_SetSfxVolume(config.audio.sfxVolume);
672 	ARXMenu_Options_Audio_SetSpeechVolume(config.audio.speechVolume);
673 	ARXMenu_Options_Audio_SetAmbianceVolume(config.audio.ambianceVolume);
674 	ARXMenu_Options_Audio_ApplyGameVolumes();
675 
676 	ARXMenu_Options_Control_SetInvertMouse(config.input.invertMouse);
677 	ARXMenu_Options_Control_SetMouseSensitivity(config.input.mouseSensitivity);
678 
679 	g_miniMap.firstInit(&player, resources, &entities);
680 
681 	Project.torch = Color3f(1.f, 0.8f, 0.66666f);
682 	LogDebug("InitializeDanae");
683 	InitializeDanae();
684 
685 	switch(resources->getReleaseType()) {
686 
687 		case 0: LogWarning << "Neither demo nor full game data files loaded."; break;
688 
689 		case PakReader::Demo: {
690 			LogInfo << "Initialized Arx Fatalis (demo)";
691 			CrashHandler::setVariable("Data files", "demo");
692 			break;
693 		}
694 
695 		case PakReader::FullGame: {
696 			LogInfo << "Initialized Arx Fatalis (full game)";
697 			CrashHandler::setVariable("Data files", "full");
698 			break;
699 		}
700 
701 		case (int(PakReader::Demo) | int(PakReader::FullGame)): {
702 			LogWarning << "Mixed demo and full game data files!";
703 			CrashHandler::setVariable("Data files", "mixed");
704 			break;
705 		}
706 
707 		default: ARX_DEAD_CODE();
708 	}
709 
710 	return true;
711 }
712 
runGame()713 void runGame() {
714 
715 	if(initializeGame()) {
716 
717 		// Init all done, start the main loop
718 		mainApp->Run();
719 
720 		// TODO run cleanup on partial initialization
721 		shutdownGame();
722 	}
723 
724 	if(mainApp) {
725 		mainApp->Shutdown();
726 		delete mainApp;
727 		mainApp = NULL;
728 	}
729 }
730 
731 
732 //*************************************************************************************
733 // Entity * FlyingOverObject(EERIE_S2D * pos)
734 //-------------------------------------------------------------------------------------
735 // FUNCTION/RESULT:
736 //   Returns IO under cursor, be it in inventories or in scene
737 //   Returns NULL if no IO under cursor
738 //*************************************************************************************
FlyingOverObject(Vec2s * pos)739 Entity * FlyingOverObject(Vec2s * pos)
740 {
741 	Entity* io = NULL;
742 
743 	if ((io = GetFromInventory(pos)) != NULL)
744 		return io;
745 	if (InInventoryPos(pos))
746 		return NULL;
747 
748 	if ((io = InterClick(pos)) != NULL)
749 		return io;
750 
751 	return NULL;
752 }
753 
754 extern long ARX_NPC_ApplyCuts(Entity * io);
755 
756 //*************************************************************************************
757 
LoadSysTextures()758 void LoadSysTextures()
759 {
760 	char temp[256];
761 
762 	for (long i=1;i<10;i++)
763 	{
764 		sprintf(temp,"graph/particles/shine%ld", i);
765 		flaretc.shine[i]=TextureContainer::LoadUI(temp);
766 
767 	}
768 
769 	for (size_t i=0;i<SPELL_COUNT;i++)
770 	{
771 		// TODO use constructor for initialization
772 		for (long j = 0; j < 6; j++) spellicons[i].symbols[j] = RUNE_NONE;
773 		spellicons[i].level = 0;
774 		spellicons[i].spellid = SPELL_NONE;
775 		spellicons[i].tc = NULL;
776 		spellicons[i].bSecret = false;
777 		spellicons[i].bDuration = true;
778 		spellicons[i].bAudibleAtStart = false;
779 	}
780 
781 	long i;
782 
783 	SPELL_ICON * current;
784 
785 	// Magic_Sight Level 1
786 	current=&spellicons[SPELL_MAGIC_SIGHT];
787 	current->name = getLocalised("system_spell_name_magic_sight");
788 	current->description = getLocalised("system_spell_description_magic_sight");
789 	current->level=1;
790 	current->spellid=SPELL_MAGIC_SIGHT;
791 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_magic_sight");
792 	current->symbols[0]=RUNE_MEGA;
793 	current->symbols[1]=RUNE_VISTA;
794 
795 	// Magic_Missile Level 1
796 	current=&spellicons[SPELL_MAGIC_MISSILE];
797 	current->name = getLocalised("system_spell_name_magic_projectile");
798 	current->description = getLocalised("system_spell_description_magic_projectile");
799 	current->level=1;
800 	current->spellid=SPELL_MAGIC_MISSILE;
801 	current->bDuration = false;
802 	current->bAudibleAtStart = true;
803 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_magic_missile");
804 	current->symbols[0]=RUNE_AAM;
805 	current->symbols[1]=RUNE_TAAR;
806 
807 	// Ignit Level 1
808 	current=&spellicons[SPELL_IGNIT];
809 	current->name = getLocalised("system_spell_name_ignit");
810 	current->description = getLocalised("system_spell_description_ignit");
811 	current->level=1;
812 	current->spellid=SPELL_IGNIT;
813 	current->bDuration = false;
814 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_ignite");
815 	current->symbols[0]=RUNE_AAM;
816 	current->symbols[1]=RUNE_YOK;
817 
818 	// Douse Level 1
819 	current=&spellicons[SPELL_DOUSE];
820 	current->name = getLocalised("system_spell_name_douse");
821 	current->description = getLocalised("system_spell_description_douse");
822 	current->level=1;
823 	current->spellid=SPELL_DOUSE;
824 	current->bDuration = false;
825 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_douse");
826 	current->symbols[0]=RUNE_NHI;
827 	current->symbols[1]=RUNE_YOK;
828 
829 	// Activate_Portal Level 1
830 	current=&spellicons[SPELL_ACTIVATE_PORTAL];
831 	current->name = getLocalised("system_spell_name_activate_portal");
832 	current->description = getLocalised("system_spell_description_activate_portal");
833 	current->level=1;
834 	current->spellid=SPELL_ACTIVATE_PORTAL;
835 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_activate_portal");
836 	current->symbols[0]=RUNE_MEGA;
837 	current->symbols[1]=RUNE_SPACIUM;
838 	current->bSecret = true;
839 
840 	// Heal Level 2
841 	current=&spellicons[SPELL_HEAL];
842 	current->name = getLocalised("system_spell_name_heal");
843 	current->description = getLocalised("system_spell_description_heal");
844 	current->level=2;
845 	current->spellid=SPELL_HEAL;
846 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_heal");
847 	current->symbols[0]=RUNE_MEGA;
848 	current->symbols[1]=RUNE_VITAE;
849 
850 	// Detect_trap Level 2
851 	current=&spellicons[SPELL_DETECT_TRAP];
852 	current->name = getLocalised("system_spell_name_detect_trap");
853 	current->description = getLocalised("system_spell_description_detect_trap");
854 	current->level=2;
855 	current->spellid=SPELL_DETECT_TRAP;
856 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_detect_trap");
857 	current->symbols[0]=RUNE_MORTE;
858 	current->symbols[1]=RUNE_COSUM;
859 	current->symbols[2]=RUNE_VISTA;
860 
861 	// Armor Level 2
862 	current=&spellicons[SPELL_ARMOR];
863 	current->name = getLocalised("system_spell_name_armor");
864 	current->description = getLocalised("system_spell_description_armor");
865 	current->level=2;
866 	current->spellid=SPELL_ARMOR;
867 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_armor");
868 	current->symbols[0]=RUNE_MEGA;
869 	current->symbols[1]=RUNE_KAOM;
870 
871 	// Lower Armor Level 2
872 	current=&spellicons[SPELL_LOWER_ARMOR];
873 	current->name = getLocalised("system_spell_name_lower_armor");
874 	current->description = getLocalised("system_spell_description_lower_armor");
875 	current->level=2;
876 	current->spellid=SPELL_LOWER_ARMOR;
877 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_lower_armor");
878 	current->symbols[0]=RUNE_RHAA;
879 	current->symbols[1]=RUNE_KAOM;
880 
881 	// Harm Level 2
882 	current=&spellicons[SPELL_HARM];
883 	current->name = getLocalised("system_spell_name_harm");
884 	current->description = getLocalised("system_spell_description_harm");
885 	current->level=2;
886 	current->spellid=SPELL_HARM;
887 	current->bAudibleAtStart = true;
888 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_harm");
889 	current->symbols[0]=RUNE_RHAA;
890 	current->symbols[1]=RUNE_VITAE;
891 	current->bSecret = true;
892 
893 	// Speed Level 3
894 	current=&spellicons[SPELL_SPEED];
895 	current->name = getLocalised("system_spell_name_speed");
896 	current->description = getLocalised("system_spell_description_speed");
897 	current->level=3;
898 	current->spellid=SPELL_SPEED;
899 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_speed");
900 	current->symbols[0]=RUNE_MEGA;
901 	current->symbols[1]=RUNE_MOVIS;
902 
903 	// Reveal Level 3
904 	current=&spellicons[SPELL_DISPELL_ILLUSION];
905 	current->name = getLocalised("system_spell_name_reveal");
906 	current->description = getLocalised("system_spell_description_reveal");
907 	current->level=3;
908 	current->spellid=SPELL_DISPELL_ILLUSION;
909 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_reveal");
910 	current->symbols[0]=RUNE_NHI;
911 	current->symbols[1]=RUNE_STREGUM;
912 	current->symbols[2]=RUNE_VISTA;
913 
914 	// Fireball Level 3
915 	current=&spellicons[SPELL_FIREBALL];
916 	current->name = getLocalised("system_spell_name_fireball");
917 	current->description = getLocalised("system_spell_description_fireball");
918 	current->level=3;
919 	current->spellid=SPELL_FIREBALL;
920 	current->bDuration = false;
921 	current->bAudibleAtStart = true;
922 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_fireball");
923 	current->symbols[0]=RUNE_AAM;
924 	current->symbols[1]=RUNE_YOK;
925 	current->symbols[2]=RUNE_TAAR;
926 
927 	// Create Food Level 3
928 	current=&spellicons[SPELL_CREATE_FOOD];
929 	current->name = getLocalised("system_spell_name_create_food");
930 	current->description = getLocalised("system_spell_description_create_food");
931 	current->level=3;
932 	current->spellid=SPELL_CREATE_FOOD;
933 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_create_food");
934 	current->symbols[0]=RUNE_AAM;
935 	current->symbols[1]=RUNE_VITAE;
936 	current->symbols[2]=RUNE_COSUM;
937 
938 	// Ice Projectile Level 3
939 	current=&spellicons[SPELL_ICE_PROJECTILE];
940 	current->name = getLocalised("system_spell_name_ice_projectile");
941 	current->description = getLocalised("system_spell_description_ice_projectile");
942 	current->level=3;
943 	current->spellid=SPELL_ICE_PROJECTILE;
944 	current->bDuration = false;
945 	current->bAudibleAtStart = true;
946 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_iceball");
947 	current->symbols[0]=RUNE_AAM;
948 	current->symbols[1]=RUNE_FRIDD;
949 	current->symbols[2]=RUNE_TAAR;
950 	current->bSecret = true;
951 
952 	// Bless Level 4
953 	current=&spellicons[SPELL_BLESS];
954 	current->name = getLocalised("system_spell_name_sanctify");
955 	current->description = getLocalised("system_spell_description_sanctify");
956 	current->level=4;
957 	current->spellid=SPELL_BLESS;
958 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_bless");
959 	current->symbols[0]=RUNE_MEGA;
960 	current->symbols[1]=RUNE_STREGUM;
961 	current->symbols[2]=RUNE_VITAE;
962 
963 	// Dispel_Field Level 4
964 	current=&spellicons[SPELL_DISPELL_FIELD];
965 	current->name = getLocalised("system_spell_name_dispell_field");
966 	current->description = getLocalised("system_spell_description_dispell_field");
967 	current->level=4;
968 	current->spellid=SPELL_DISPELL_FIELD;
969 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_dispell_field");
970 	current->symbols[0]=RUNE_NHI;
971 
972 	current->symbols[1]=RUNE_SPACIUM;
973 
974 	// Cold Protection Level 4
975 	current=&spellicons[SPELL_COLD_PROTECTION];
976 	current->name = getLocalised("system_spell_name_cold_protection");
977 	current->description = getLocalised("system_spell_description_cold_protection");
978 	current->level=4;
979 	current->spellid=SPELL_COLD_PROTECTION;
980 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_protection_cold");
981 	current->symbols[0]=RUNE_FRIDD;
982 	current->symbols[1]=RUNE_KAOM;
983 	current->bSecret = true;
984 
985 	// Fire Protection Level 4
986 	current=&spellicons[SPELL_FIRE_PROTECTION];
987 	current->name = getLocalised("system_spell_name_fire_protection");
988 	current->description = getLocalised("system_spell_description_fire_protection");
989 	current->level=4;
990 	current->spellid=SPELL_FIRE_PROTECTION;
991 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_protection_fire");
992 	current->symbols[0]=RUNE_YOK;
993 	current->symbols[1]=RUNE_KAOM;
994 
995 	// Telekinesis Level 4
996 	current=&spellicons[SPELL_TELEKINESIS];
997 	current->name = getLocalised("system_spell_name_telekinesis");
998 	current->description = getLocalised("system_spell_description_telekinesis");
999 	current->level=4;
1000 	current->spellid=SPELL_TELEKINESIS;
1001 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_telekinesis");
1002 	current->symbols[0]=RUNE_SPACIUM;
1003 	current->symbols[1]=RUNE_COMUNICATUM;
1004 
1005 	// Curse Level 4
1006 	current=&spellicons[SPELL_CURSE];
1007 	current->name = getLocalised("system_spell_name_curse");
1008 	current->description = getLocalised("system_spell_description_curse");
1009 	current->level=4;
1010 	current->spellid=SPELL_CURSE;
1011 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_curse");
1012 	current->symbols[0]=RUNE_RHAA;
1013 	current->symbols[1]=RUNE_STREGUM;
1014 	current->symbols[2]=RUNE_VITAE;
1015 	current->bSecret = true;
1016 
1017 	// Rune of Guarding Level 5
1018 	current=&spellicons[SPELL_RUNE_OF_GUARDING];
1019 	current->name = getLocalised("system_spell_name_rune_guarding");
1020 	current->description = getLocalised("system_spell_description_rune_guarding");
1021 	current->level=5;
1022 	current->spellid=SPELL_RUNE_OF_GUARDING;
1023 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_rune_guarding");
1024 	current->symbols[0]=RUNE_AAM;
1025 	current->symbols[1]=RUNE_MORTE;
1026 	current->symbols[2]=RUNE_COSUM;
1027 
1028 	// Levitate Level 5
1029 	current=&spellicons[SPELL_LEVITATE];
1030 	current->name = getLocalised("system_spell_name_levitate");
1031 	current->description = getLocalised("system_spell_description_levitate");
1032 	current->level=5;
1033 	current->spellid=SPELL_LEVITATE;
1034 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_levitate");
1035 	current->symbols[0]=RUNE_MEGA;
1036 	current->symbols[1]=RUNE_SPACIUM;
1037 	current->symbols[2]=RUNE_MOVIS;
1038 
1039 	// Cure Poison Level 5
1040 	current=&spellicons[SPELL_CURE_POISON];
1041 	current->name = getLocalised("system_spell_name_cure_poison");
1042 	current->description = getLocalised("system_spell_description_cure_poison");
1043 	current->level=5;
1044 	current->spellid=SPELL_CURE_POISON;
1045 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_cure_poison");
1046 	current->symbols[0]=RUNE_NHI;
1047 	current->symbols[1]=RUNE_CETRIUS;
1048 
1049 	// Repel Undead Level 5
1050 	current=&spellicons[SPELL_REPEL_UNDEAD];
1051 	current->name = getLocalised("system_spell_name_repel_undead");
1052 	current->description = getLocalised("system_spell_description_repel_undead");
1053 	current->level=5;
1054 	current->spellid=SPELL_REPEL_UNDEAD;
1055 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_repel_undead");
1056 	current->symbols[0]=RUNE_MORTE;
1057 	current->symbols[1]=RUNE_KAOM;
1058 
1059 	// Poison Projection Level 5
1060 	current=&spellicons[SPELL_POISON_PROJECTILE];
1061 	current->name = getLocalised("system_spell_name_poison_projection");
1062 	current->description = getLocalised("system_spell_description_poison_projection");
1063 	current->level=5;
1064 	current->spellid=SPELL_POISON_PROJECTILE;
1065 	current->bDuration = false;
1066 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_poison_projection");
1067 	current->symbols[0]=RUNE_AAM;
1068 	current->symbols[1]=RUNE_CETRIUS;
1069 	current->symbols[2]=RUNE_TAAR;
1070 	current->bSecret = true;
1071 
1072 	// Raise Dead Level 6
1073 	current=&spellicons[SPELL_RISE_DEAD];
1074 	current->name = getLocalised("system_spell_name_raise_dead");
1075 	current->description = getLocalised("system_spell_description_raise_dead");
1076 	current->level=6;
1077 	current->spellid=SPELL_RISE_DEAD;
1078 	current->bAudibleAtStart = true;
1079 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_raise_dead");
1080 	current->symbols[0]=RUNE_AAM;
1081 	current->symbols[1]=RUNE_MORTE;
1082 	current->symbols[2]=RUNE_VITAE;
1083 
1084 	// Paralyse Dead Level 6
1085 	current=&spellicons[SPELL_PARALYSE];
1086 	current->name = getLocalised("system_spell_name_paralyse");
1087 	current->description = getLocalised("system_spell_description_paralyse");
1088 	current->level=6;
1089 	current->spellid=SPELL_PARALYSE;
1090 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_paralyse");
1091 	current->symbols[0]=RUNE_NHI;
1092 	current->symbols[1]=RUNE_MOVIS;
1093 
1094 	// Create Field Dead Level 6
1095 	current=&spellicons[SPELL_CREATE_FIELD];
1096 	current->name = getLocalised("system_spell_name_create_field");
1097 	current->description = getLocalised("system_spell_description_create_field");
1098 	current->level=6;
1099 	current->spellid=SPELL_CREATE_FIELD;
1100 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_create_field");
1101 	current->symbols[0]=RUNE_AAM;
1102 	current->symbols[1]=RUNE_KAOM;
1103 	current->symbols[2]=RUNE_SPACIUM;
1104 
1105 	// Disarm Trap Level 6
1106 	current=&spellicons[SPELL_DISARM_TRAP];
1107 	current->name = getLocalised("system_spell_name_disarm_trap");
1108 	current->description = getLocalised("system_spell_description_disarm_trap");
1109 	current->level=6;
1110 	current->spellid=SPELL_DISARM_TRAP;
1111 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_disarm_trap");
1112 	current->symbols[0]=RUNE_NHI;
1113 	current->symbols[1]=RUNE_MORTE;
1114 	current->symbols[2]=RUNE_COSUM;
1115 
1116 	// Slow_Down Level 6 // SECRET SPELL
1117 	current=&spellicons[SPELL_SLOW_DOWN];
1118 	current->name = getLocalised("system_spell_name_slowdown");
1119 	current->description = getLocalised("system_spell_description_slowdown");
1120 	current->level=6;
1121 	current->spellid=SPELL_SLOW_DOWN;
1122 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_slow_down");
1123 	current->symbols[0]=RUNE_RHAA;
1124 	current->symbols[1]=RUNE_MOVIS;
1125 	current->bSecret = true;
1126 
1127 	// Flying Eye Level 7
1128 	current=&spellicons[SPELL_FLYING_EYE];
1129 	current->name = getLocalised("system_spell_name_flying_eye");
1130 	current->description = getLocalised("system_spell_description_flying_eye");
1131 	current->level=7;
1132 	current->spellid=SPELL_FLYING_EYE;
1133 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_flying_eye");
1134 	current->symbols[0]=RUNE_VISTA;
1135 	current->symbols[1]=RUNE_MOVIS;
1136 
1137 	// Fire Field Eye Level 7
1138 	current=&spellicons[SPELL_FIRE_FIELD];
1139 	current->name = getLocalised("system_spell_name_fire_field");
1140 	current->description = getLocalised("system_spell_description_fire_field");
1141 	current->level=7;
1142 	current->spellid=SPELL_FIRE_FIELD;
1143 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_create_fire_field");
1144 	current->symbols[0]=RUNE_AAM;
1145 	current->symbols[1]=RUNE_YOK;
1146 	current->symbols[2]=RUNE_SPACIUM;
1147 
1148 	// Ice Field Level 7
1149 	current=&spellicons[SPELL_ICE_FIELD];
1150 	current->name = getLocalised("system_spell_name_ice_field");
1151 	current->description = getLocalised("system_spell_description_ice_field");
1152 	current->level=7;
1153 	current->spellid=SPELL_ICE_FIELD;
1154 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_create_cold_field");
1155 	current->symbols[0]=RUNE_AAM;
1156 	current->symbols[1]=RUNE_FRIDD;
1157 	current->symbols[2]=RUNE_SPACIUM;
1158 	current->bSecret = true;
1159 
1160 	// Lightning Strike Level 7
1161 	current=&spellicons[SPELL_LIGHTNING_STRIKE];
1162 	current->name = getLocalised("system_spell_name_lightning_strike");
1163 	current->description = getLocalised("system_spell_description_lightning_strike");
1164 	current->level=7;
1165 	current->spellid=SPELL_LIGHTNING_STRIKE;
1166 	current->bDuration = false;
1167 	current->bAudibleAtStart = true;
1168 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_lightning_strike");
1169 	current->symbols[0]=RUNE_AAM;
1170 	current->symbols[1]=RUNE_FOLGORA;
1171 	current->symbols[2]=RUNE_TAAR;
1172 
1173 	// Confusion Level 7
1174 	current=&spellicons[SPELL_CONFUSE];
1175 	current->name = getLocalised("system_spell_name_confuse");
1176 	current->description = getLocalised("system_spell_description_confuse");
1177 	current->level=7;
1178 	current->spellid=SPELL_CONFUSE;
1179 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_confuse");
1180 	current->symbols[0]=RUNE_RHAA;
1181 	current->symbols[1]=RUNE_VISTA;
1182 
1183 	// Invisibility Level 8
1184 	current=&spellicons[SPELL_INVISIBILITY];
1185 	current->name = getLocalised("system_spell_name_invisibility");
1186 	current->description = getLocalised("system_spell_description_invisibility");
1187 	current->level=8;
1188 	current->spellid=SPELL_INVISIBILITY;
1189 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_invisibility");
1190 	current->symbols[0]=RUNE_NHI;
1191 	current->symbols[1]=RUNE_VISTA;
1192 
1193 	// Mana Drain Level 8
1194 	current=&spellicons[SPELL_MANA_DRAIN];
1195 	current->name = getLocalised("system_spell_name_mana_drain");
1196 	current->description = getLocalised("system_spell_description_mana_drain");
1197 	current->level=8;
1198 	current->spellid=SPELL_MANA_DRAIN;
1199 	current->bAudibleAtStart = true;
1200 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_drain_mana");
1201 	current->symbols[0]=RUNE_STREGUM;
1202 	current->symbols[1]=RUNE_MOVIS;
1203 
1204 	// Explosion Level 8
1205 	current=&spellicons[SPELL_EXPLOSION];
1206 	current->name = getLocalised("system_spell_name_explosion");
1207 	current->description = getLocalised("system_spell_description_explosion");
1208 	current->level=8;
1209 	current->spellid=SPELL_EXPLOSION;
1210 	current->bDuration = false;
1211 	current->bAudibleAtStart = true;
1212 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_explosion");
1213 	current->symbols[0]=RUNE_AAM;
1214 	current->symbols[1]=RUNE_MEGA;
1215 	current->symbols[2]=RUNE_MORTE;
1216 
1217 	// Enchant Weapon Level 8
1218 	current=&spellicons[SPELL_ENCHANT_WEAPON];
1219 	current->name = getLocalised("system_spell_name_enchant_weapon");
1220 	current->description = getLocalised("system_spell_description_enchant_weapon");
1221 	current->level=8;
1222 	current->spellid=SPELL_ENCHANT_WEAPON;
1223 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_enchant_weapon");
1224 	current->symbols[0]=RUNE_MEGA;
1225 	current->symbols[1]=RUNE_STREGUM;
1226 	current->symbols[2]=RUNE_COSUM;
1227 
1228 	// Life Drain Level 8 // SECRET SPELL
1229 	current=&spellicons[SPELL_LIFE_DRAIN];
1230 	current->name = getLocalised("system_spell_name_life_drain");
1231 	current->description = getLocalised("system_spell_description_life_drain");
1232 	current->level=8;
1233 	current->spellid=SPELL_LIFE_DRAIN;
1234 	current->bAudibleAtStart = true;
1235 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_drain_life");
1236 	current->symbols[0]=RUNE_VITAE;
1237 	current->symbols[1]=RUNE_MOVIS;
1238 	current->bSecret = true;
1239 
1240 	// Summon Creature Level 9
1241 	current=&spellicons[SPELL_SUMMON_CREATURE];
1242 	current->name = getLocalised("system_spell_name_summon_creature");
1243 	current->description = getLocalised("system_spell_description_summon_creature");
1244 	current->level=9;
1245 	current->spellid=SPELL_SUMMON_CREATURE;
1246 	current->bAudibleAtStart = true;
1247 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_summon_creature");
1248 	current->symbols[0]=RUNE_AAM;
1249 	current->symbols[1]=RUNE_VITAE;
1250 	current->symbols[2]=RUNE_TERA;
1251 
1252 	// FAKE Summon Creature Level 9
1253 	current=&spellicons[SPELL_FAKE_SUMMON];
1254 	current->name = getLocalised("system_spell_name_summon_creature");
1255 	current->description = getLocalised("system_spell_description_summon_creature");
1256 	current->level=9;
1257 	current->spellid=SPELL_FAKE_SUMMON;
1258 	current->bAudibleAtStart = true;
1259 	current->bSecret = true;
1260 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_summon_creature");
1261 	current->symbols[0]=RUNE_AAM;
1262 	current->symbols[1]=RUNE_VITAE;
1263 	current->symbols[2]=RUNE_TERA;
1264 
1265 	// Negate Magic Level 9
1266 	current=&spellicons[SPELL_NEGATE_MAGIC];
1267 	current->name = getLocalised("system_spell_name_negate_magic");
1268 	current->description = getLocalised("system_spell_description_negate_magic");
1269 	current->level=9;
1270 	current->spellid=SPELL_NEGATE_MAGIC;
1271 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_negate_magic");
1272 	current->symbols[0]=RUNE_NHI;
1273 	current->symbols[1]=RUNE_STREGUM;
1274 	current->symbols[2]=RUNE_SPACIUM;
1275 
1276 	// Incinerate Level 9
1277 	current=&spellicons[SPELL_INCINERATE];
1278 	current->name = getLocalised("system_spell_name_incinerate");
1279 	current->description = getLocalised("system_spell_description_incinerate");
1280 	current->level=9;
1281 	current->spellid=SPELL_INCINERATE;
1282 	current->bDuration = false;
1283 	current->bAudibleAtStart = true;
1284 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_incinerate");
1285 	current->symbols[0]=RUNE_AAM;
1286 	current->symbols[1]=RUNE_MEGA;
1287 	current->symbols[2]=RUNE_YOK;
1288 
1289 	// Mass paralyse Creature Level 9
1290 	current=&spellicons[SPELL_MASS_PARALYSE];
1291 	current->name = getLocalised("system_spell_name_mass_paralyse");
1292 	current->description = getLocalised("system_spell_description_mass_paralyse");
1293 	current->level=9;
1294 	current->spellid=SPELL_MASS_PARALYSE;
1295 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_mass_paralyse");
1296 	current->symbols[0]=RUNE_MEGA;
1297 	current->symbols[1]=RUNE_NHI;
1298 	current->symbols[2]=RUNE_MOVIS;
1299 
1300 	// Mass Lightning Strike Level 10
1301 	current=&spellicons[SPELL_MASS_LIGHTNING_STRIKE];
1302 	current->name = getLocalised("system_spell_name_mass_lightning_strike");
1303 	current->description = getLocalised("system_spell_description_mass_lightning_strike");
1304 	current->level=10;
1305 	current->spellid=SPELL_MASS_LIGHTNING_STRIKE;
1306 	current->bDuration = false;
1307 	current->bAudibleAtStart = true;
1308 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_mass_lighting_strike");
1309 	current->symbols[0]=RUNE_AAM;
1310 	current->symbols[1]=RUNE_FOLGORA;
1311 	current->symbols[2]=RUNE_SPACIUM;
1312 
1313 	// Control Target Level 10
1314 	current=&spellicons[SPELL_CONTROL_TARGET];
1315 	current->name = getLocalised("system_spell_name_control_target");
1316 	current->description = getLocalised("system_spell_description_control_target");
1317 	current->level=10;
1318 	current->spellid=SPELL_CONTROL_TARGET;
1319 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_control_target");
1320 	current->symbols[0]=RUNE_MOVIS;
1321 	current->symbols[1]=RUNE_COMUNICATUM;
1322 
1323 	// Freeze time Level 10
1324 	current=&spellicons[SPELL_FREEZE_TIME];
1325 	current->name = getLocalised("system_spell_name_freeze_time");
1326 	current->description = getLocalised("system_spell_description_freeze_time");
1327 	current->level=10;
1328 	current->spellid=SPELL_FREEZE_TIME;
1329 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_freeze_time");
1330 	current->symbols[0] = RUNE_RHAA;
1331 	current->symbols[1]=RUNE_TEMPUS;
1332 
1333 	// Mass incinerate Level 10
1334 	current=&spellicons[SPELL_MASS_INCINERATE];
1335 	current->name = getLocalised("system_spell_name_mass_incinerate");
1336 	current->description = getLocalised("system_spell_description_mass_incinerate");
1337 	current->level=10;
1338 	current->spellid=SPELL_MASS_INCINERATE;
1339 	current->bDuration = false;
1340 	current->bAudibleAtStart = true;
1341 	current->tc=TextureContainer::LoadUI("graph/interface/icons/spell_mass_incinerate");
1342 	current->symbols[0]=RUNE_MEGA;
1343 	current->symbols[1]=RUNE_AAM;
1344 	current->symbols[2]=RUNE_MEGA;
1345 	current->symbols[3]=RUNE_YOK;
1346 
1347 	Flying_Eye=			TextureContainer::LoadUI("graph/particles/flying_eye_fx");
1348 	specular=			TextureContainer::LoadUI("graph/particles/specular");
1349 	enviro=				TextureContainer::LoadUI("graph/particles/enviro");
1350 	sphere_particle=	TextureContainer::LoadUI("graph/particles/sphere");
1351 	inventory_font=		TextureContainer::LoadUI("graph/interface/font/font10x10_inventory");
1352 	npc_fight=			TextureContainer::LoadUI("graph/interface/icons/follower_attack");
1353 	npc_follow=			TextureContainer::LoadUI("graph/interface/icons/follower_follow");
1354 	npc_stop=			TextureContainer::LoadUI("graph/interface/icons/follower_stop");
1355 	flaretc.lumignon=	TextureContainer::LoadUI("graph/particles/lumignon");
1356 	flaretc.lumignon2=	TextureContainer::LoadUI("graph/particles/lumignon2");
1357 	flaretc.plasm=		TextureContainer::LoadUI("graph/particles/plasm");
1358 	tflare=				TextureContainer::LoadUI("graph/particles/flare");
1359 	ombrignon=			TextureContainer::LoadUI("graph/particles/ombrignon");
1360 	TextureContainer::LoadUI("graph/particles/teleportae");
1361 	TC_fire=			TextureContainer::LoadUI("graph/particles/fire");
1362 	TC_fire2=			TextureContainer::LoadUI("graph/particles/fire2");
1363 	TC_smoke=			TextureContainer::LoadUI("graph/particles/smoke");
1364 	TextureContainer::LoadUI("graph/particles/missile");
1365 	Z_map = TextureContainer::LoadUI("graph/interface/misc/z-map");
1366 	Boom=				TextureContainer::LoadUI("graph/particles/boom");
1367 	lightsource_tc=		TextureContainer::LoadUI("graph/particles/light");
1368 	stealth_gauge_tc=	TextureContainer::LoadUI("graph/interface/icons/stealth_gauge");
1369 	arx_logo_tc=		TextureContainer::LoadUI("graph/interface/icons/arx_logo_32");
1370 	iconequip[0]=		TextureContainer::LoadUI("graph/interface/icons/equipment_sword");
1371 	iconequip[1]=		TextureContainer::LoadUI("graph/interface/icons/equipment_shield");
1372 	iconequip[2]=		TextureContainer::LoadUI("graph/interface/icons/equipment_helm");
1373 	iconequip[3]=		TextureContainer::LoadUI("graph/interface/icons/equipment_chest");
1374 	iconequip[4]=		TextureContainer::LoadUI("graph/interface/icons/equipment_leggings");
1375 	mecanism_tc=		TextureContainer::LoadUI("graph/interface/cursors/mecanism");
1376 	arrow_left_tc=		TextureContainer::LoadUI("graph/interface/icons/arrow_left");
1377 
1378 	for (i=0;i<MAX_EXPLO;i++)
1379 	{
1380 		char temp[256];
1381 		sprintf(temp,"graph/particles/fireb_%02ld",i+1);
1382 		explo[i]= TextureContainer::LoadUI(temp);
1383 	}
1384 
1385 	blood_splat=TextureContainer::LoadUI("graph/particles/new_blood2");
1386 
1387 	EERIE_DRAW_sphere_particle=sphere_particle;
1388 	TextureContainer::LoadUI("graph/particles/square");
1389 
1390 	TextureContainer::LoadUI("graph/particles/fire_hit");
1391 	TextureContainer::LoadUI("graph/particles/light");
1392 	TextureContainer::LoadUI("graph/particles/blood01");
1393 	TextureContainer::LoadUI("graph/particles/cross");
1394 
1395 	//INTERFACE LOADING
1396 	TextureContainer::LoadUI("graph/interface/bars/empty_gauge_red");
1397 	TextureContainer::LoadUI("graph/interface/bars/empty_gauge_blue");
1398 	TextureContainer::LoadUI("graph/interface/bars/filled_gauge_blue");
1399 	TextureContainer::LoadUI("graph/interface/bars/filled_gauge_red");
1400 	TextureContainer::LoadUI("graph/interface/icons/book");
1401 	TextureContainer::LoadUI("graph/interface/icons/backpack");
1402 	TextureContainer::LoadUI("graph/interface/icons/lvl_up");
1403 	TextureContainer::LoadUI("graph/interface/icons/steal");
1404 	TextureContainer::LoadUI("graph/interface/icons/cant_steal_item");
1405 	TextureContainer::LoadUI("graph/interface/inventory/hero_inventory");
1406 	TextureContainer::LoadUI("graph/interface/inventory/scroll_up");
1407 	TextureContainer::LoadUI("graph/interface/inventory/scroll_down");
1408 	TextureContainer::LoadUI("graph/interface/inventory/hero_inventory_link");
1409 	TextureContainer::LoadUI("graph/interface/inventory/ingame_inventory");
1410 	TextureContainer::LoadUI("graph/interface/inventory/gold");
1411 
1412 	TextureContainer::LoadUI("graph/interface/inventory/inv_pick");
1413 	TextureContainer::LoadUI("graph/interface/inventory/inv_close");
1414 
1415 	// MENU2
1416 	TextureContainer::LoadUI("graph/interface/cursors/cursor00");
1417 	TextureContainer::LoadUI("graph/interface/cursors/cursor01");
1418 	TextureContainer::LoadUI("graph/interface/cursors/cursor02");
1419 	TextureContainer::LoadUI("graph/interface/cursors/cursor03");
1420 	TextureContainer::LoadUI("graph/interface/cursors/cursor04");
1421 	TextureContainer::LoadUI("graph/interface/cursors/cursor05");
1422 	TextureContainer::LoadUI("graph/interface/cursors/cursor06");
1423 	TextureContainer::LoadUI("graph/interface/cursors/cursor07");
1424 	TextureContainer::LoadUI("graph/interface/cursors/cruz");
1425 	TextureContainer::LoadUI("graph/interface/menus/menu_main_background", TextureContainer::NoColorKey);
1426 	TextureContainer::LoadUI("graph/interface/menus/menu_console_background");
1427 	TextureContainer::LoadUI("graph/interface/menus/menu_console_background_border");
1428 
1429 	//CURSORS LOADING
1430 	TextureContainer::LoadUI("graph/interface/cursors/cursor");
1431 	TextureContainer::LoadUI("graph/interface/cursors/magic");
1432 	TextureContainer::LoadUI("graph/interface/cursors/interaction_on");
1433 	TextureContainer::LoadUI("graph/interface/cursors/interaction_off");
1434 	TextureContainer::LoadUI("graph/interface/cursors/target_on");
1435 	TextureContainer::LoadUI("graph/interface/cursors/target_off");
1436 	TextureContainer::LoadUI("graph/interface/cursors/drop");
1437 	TextureContainer::LoadUI("graph/interface/cursors/throw");
1438 
1439 	for(i = 0; i < 8; i++) {
1440 		char temp[256];
1441 		sprintf(temp,"graph/interface/cursors/cursor%02ld", i);
1442 		scursor[i] = TextureContainer::LoadUI(temp);
1443 	}
1444 
1445 	pTCCrossHair = TextureContainer::LoadUI("graph/interface/cursors/cruz");
1446 
1447 	TextureContainer::LoadUI("graph/interface/bars/aim_empty");
1448 	TextureContainer::LoadUI("graph/interface/bars/aim_maxi");
1449 	TextureContainer::LoadUI("graph/interface/bars/flash_gauge");
1450 }
1451 
ClearSysTextures()1452 void ClearSysTextures() {
1453 	for(size_t i = 0; i < SPELL_COUNT; i++) {
1454 		if(!spellicons[i].name.empty())
1455 			//free(spellicons[i].name);
1456 			spellicons[i].name.clear();
1457 
1458 		if(!spellicons[i].description.empty())
1459 			//free(spellicons[i].description);
1460 			spellicons[i].description.clear();
1461 	}
1462 }
1463 
PlayerLaunchArrow_Test(float aimratio,float poisonous,Vec3f * pos,Anglef * angle)1464 static void PlayerLaunchArrow_Test(float aimratio, float poisonous, Vec3f * pos, Anglef * angle) {
1465 
1466 	Vec3f vect;
1467 	Vec3f dvect;
1468 	EERIEMATRIX mat;
1469 	EERIE_QUAT quat;
1470 
1471 	Vec3f position = *pos;
1472 	float anglea = radians(angle->a);
1473 	float angleb = radians(angle->b);
1474 	vect.x=-EEsin(angleb)*EEcos(anglea);
1475 	vect.y= EEsin(anglea);
1476 	vect.z= EEcos(angleb)*EEcos(anglea);
1477 	Vec3f upvect(0,0,-1);
1478 	VRotateX(&upvect,anglea);
1479 	VRotateY(&upvect,angleb);
1480 	upvect = Vec3f(0,-1,0);
1481 	VRotateX(&upvect,anglea);
1482 	VRotateY(&upvect,angleb);
1483 	MatrixSetByVectors(&mat,&dvect,&upvect);
1484 	QuatFromMatrix(quat,mat);
1485 	float velocity = aimratio + 0.3f;
1486 
1487 	if (velocity<0.9f) velocity=0.9f;
1488 
1489 	Vec3f v1,v2;
1490 	Vec3f vv(0,0,1);
1491 	float aa=angle->a;
1492 	float ab=90-angle->b;
1493 	Vector_RotateZ(&v1,&vv,aa);
1494 	VRotateY(&v1,ab);
1495 	vv = Vec3f(0,-1,0);
1496 	Vector_RotateZ(&v2,&vv,aa);
1497 	VRotateY(&v2,ab);
1498 	EERIEMATRIX tmat;
1499 	MatrixSetByVectors(&tmat,&v1,&v2);
1500 	QuatFromMatrix(quat,tmat);
1501 
1502 	float wd=(float)ARX_EQUIPMENT_Apply(
1503 		entities.player(),IO_EQUIPITEM_ELEMENT_Damages,1);
1504 
1505 	float weapon_damages=wd;
1506 
1507 	float damages=
1508 		weapon_damages
1509 		*(1.f+
1510 		(float)(player.Full_Skill_Projectile + player.Full_Attribute_Dexterity )*( 1.0f / 50 ));
1511 
1512 	ARX_THROWN_OBJECT_Throw(
1513 										0, //source
1514 										&position,
1515 										&vect,
1516 										&upvect,
1517 										&quat,
1518 							velocity,
1519 										damages,
1520 										poisonous); //damages
1521 }
1522 
1523 extern long sp_max;
PlayerLaunchArrow(float aimratio,float poisonous)1524 void PlayerLaunchArrow(float aimratio,float poisonous)
1525 {
1526 	Vec3f position;
1527 	Vec3f vect;
1528 	Vec3f dvect;
1529 	EERIEMATRIX mat;
1530 	EERIE_QUAT quat;
1531 	float anglea;
1532 	float angleb;
1533 	float velocity;
1534 
1535 	if ((sp_max) && (poisonous<3.f))
1536 		poisonous=3.f;
1537 
1538 	position.x=player.pos.x;
1539 	position.y=player.pos.y+40.f;
1540 	position.z=player.pos.z;
1541 
1542 	if (entities.player()->obj->fastaccess.left_attach>=0)
1543 	{
1544 		position = entities.player()->obj->vertexlist3[entities.player()->obj->fastaccess.left_attach].v;
1545 	}
1546 
1547 	anglea=radians(player.angle.a);
1548 	angleb=radians(player.angle.b);
1549 	vect.x=-EEsin(angleb)*EEcos(anglea);
1550 	vect.y= EEsin(anglea);
1551 	vect.z= EEcos(angleb)*EEcos(anglea);
1552 
1553 	Vec3f upvect(0,0,-1);
1554 	VRotateX(&upvect,anglea);
1555 	VRotateY(&upvect,angleb);
1556 
1557 	upvect = Vec3f(0,-1,0);
1558 	VRotateX(&upvect,anglea);
1559 	VRotateY(&upvect,angleb);
1560 	MatrixSetByVectors(&mat,&dvect,&upvect);
1561 	QuatFromMatrix(quat,mat);
1562 
1563 	velocity=(aimratio+0.3f);
1564 
1565 	if (velocity<0.9f) velocity=0.9f;
1566 
1567 	Vec3f v1,v2;
1568 	Vec3f vv(0,0,1);
1569 	float aa=player.angle.a;
1570 	float ab=90-player.angle.b;
1571 	Vector_RotateZ(&v1,&vv,aa);
1572 	VRotateY(&v1,ab);
1573 	vv = Vec3f(0,-1,0);
1574 	Vector_RotateZ(&v2,&vv,aa);
1575 	VRotateY(&v2,ab);
1576 	EERIEMATRIX tmat;
1577 	MatrixSetByVectors(&tmat,&v1,&v2);
1578 	QuatFromMatrix(quat,tmat);
1579 
1580 	float wd=(float)ARX_EQUIPMENT_Apply(
1581 		entities.player(),IO_EQUIPITEM_ELEMENT_Damages,1);
1582 
1583 	float weapon_damages=wd;
1584 
1585 	float damages=
1586 		weapon_damages
1587 		*(1.f+
1588 		(float)(player.Full_Skill_Projectile + player.Full_Attribute_Dexterity )*( 1.0f / 50 ));
1589 
1590 	ARX_THROWN_OBJECT_Throw(
1591 										0, //source
1592 										&position,
1593 										&vect,
1594 										&upvect,
1595 										&quat,
1596 							velocity,
1597 										damages,
1598 										poisonous); //damages
1599 
1600 	if (sp_max)
1601 	{
1602 		Anglef angle;
1603 		Vec3f pos;
1604 		pos.x=player.pos.x;
1605 		pos.y=player.pos.y+40.f;
1606 		pos.z=player.pos.z;
1607 		angle.a=player.angle.a;
1608 		angle.b=player.angle.b+8;
1609 		angle.g=player.angle.g;
1610 		PlayerLaunchArrow_Test(aimratio,poisonous,&pos,&angle);
1611 		angle.a=player.angle.a;
1612 		angle.b=player.angle.b-8;
1613 		PlayerLaunchArrow_Test(aimratio,poisonous,&pos,&angle);
1614 		angle.a=player.angle.a;
1615 		angle.b=player.angle.b+4.f;
1616 		PlayerLaunchArrow_Test(aimratio,poisonous,&pos,&angle);
1617 		angle.a=player.angle.a;
1618 		angle.b=player.angle.b-4.f;
1619 		PlayerLaunchArrow_Test(aimratio,poisonous,&pos,&angle);
1620 	}
1621 }
1622 
1623 extern unsigned long LAST_JUMP_ENDTIME;
1624 
1625 //*************************************************************************************
1626 // Switches from/to Game Mode/Editor Mode
1627 //*************************************************************************************
SetEditMode(long ed,const bool stop_sound)1628 void SetEditMode(long ed, const bool stop_sound) {
1629 
1630 	LAST_JUMP_ENDTIME = 0;
1631 
1632 	if(!DONT_ERASE_PLAYER) {
1633 		player.life = 0.1f;
1634 	}
1635 
1636 	BOOST_FOREACH(Entity * e, entities) {
1637 		if(e && (e->show == SHOW_FLAG_HIDDEN || e->show == SHOW_FLAG_KILLED)) {
1638 			e->show = SHOW_FLAG_IN_SCENE;
1639 		}
1640 	}
1641 
1642 	RestoreAllLightsInitialStatus();
1643 
1644 	if (stop_sound) ARX_SOUND_MixerStop(ARX_SOUND_MixerGame);
1645 
1646 	RestoreInitialIOStatus();
1647 
1648 	if (ed)
1649 	{
1650 		ARX_PATH_ComputeAllBoundingBoxes();
1651 
1652 		arxtime.pause();
1653 	}
1654 	else
1655 	{
1656 		ARX_SCRIPT_ResetAll(1);
1657 		EERIE_ANIMMANAGER_PurgeUnused();
1658 	}
1659 
1660 	if(!DONT_ERASE_PLAYER) {
1661 		ARX_PLAYER_MakeFreshHero();
1662 	}
1663 
1664 }
1665 
DANAE_ReleaseAllDatasDynamic()1666 void DANAE_ReleaseAllDatasDynamic() {
1667 	delete ssol, ssol = NULL, ssol_count = 0;
1668 	delete slight, slight = NULL, slight_count = 0;
1669 	delete srune, srune = NULL, srune_count = 0;
1670 	delete smotte, smotte = NULL, smotte_count = 0;
1671 	delete stite, stite = NULL, stite_count = 0;
1672 	delete smissile, smissile = NULL, smissile_count = 0;
1673 	delete spapi, spapi = NULL, spapi_count = 0;
1674 	delete svoodoo, svoodoo = NULL, svoodoo_count = 0;
1675 }
1676 
ReleaseDanaeBeforeRun()1677 void ReleaseDanaeBeforeRun() {
1678 
1679 	delete necklace.lacet, necklace.lacet = NULL;
1680 
1681 	for(long i = 0; i < 20; i++) {
1682 		delete necklace.runes[i], necklace.runes[i] = NULL;
1683 		necklace.pTexTab[i] = NULL;
1684 	}
1685 
1686 	delete eyeballobj, eyeballobj = NULL;
1687 	delete cabal, cabal = NULL;
1688 	delete nodeobj, nodeobj = NULL;
1689 	delete fogobj, fogobj = NULL;
1690 	delete cameraobj, cameraobj = NULL;
1691 	delete markerobj, markerobj = NULL;
1692 	delete arrowobj, arrowobj = NULL;
1693 
1694 	BOOST_FOREACH(EERIE_3DOBJ * & obj, GoldCoinsObj) {
1695 		delete obj, obj = NULL;
1696 	}
1697 
1698 }
1699 
FirstTimeThings()1700 void FirstTimeThings() {
1701 
1702 	eyeball.exist=0;
1703 	WILLADDSPEECHTIME=0;
1704 	WILLADDSPEECH.clear();
1705 
1706 	if(!LOADEDD) {
1707 		RemoveAllBackgroundActions();
1708 	}
1709 
1710 	for(size_t i = 0; i < MAX_DYNLIGHTS; i++) {
1711 		DynLight[i].exist = 0;
1712 	}
1713 
1714 	arxtime.update_last_frame_time();
1715 }
1716 
1717 //*************************************************************************************
1718 
1719 long NO_GMOD_RESET=0;
1720 
FirstFrameProc()1721 void FirstFrameProc() {
1722 
1723 	if (pParticleManager == NULL)
1724 	{
1725 		pParticleManager = new ParticleManager();
1726 	}
1727 
1728 	if (!NO_GMOD_RESET)
1729 		ARX_GLOBALMODS_Reset();
1730 
1731 	NO_GMOD_RESET = 0;
1732 
1733 	STARTDRAG = Vec2s::ZERO;
1734 	DANAEMouse = Vec2s::ZERO;
1735 	bookclick = Vec2s(-1, -1);
1736 
1737 	if (!LOAD_N_DONT_ERASE) arxtime.init();
1738 
1739 	ARX_BOOMS_ClearAllPolyBooms();
1740 	ARX_DAMAGES_Reset();
1741 	ARX_MISSILES_ClearAll();
1742 	ARX_SPELLS_ClearAll();
1743 	ARX_SPELLS_ClearAllSymbolDraw();
1744 	ARX_PARTICLES_ClearAll();
1745 
1746 	if (!LOAD_N_DONT_ERASE)
1747 	{
1748 		CleanScriptLoadedIO();
1749 		RestoreInitialIOStatus();
1750 		DRAGINTER=NULL;
1751 	}
1752 
1753 	ARX_SPELLS_ResetRecognition();
1754 
1755 	FirstTimeThings();
1756 
1757 	if (!LOAD_N_DONT_ERASE)
1758 	{
1759 
1760 		CleanInventory();
1761 		ARX_SCRIPT_Timer_ClearAll();
1762 		UnlinkAllLinkedObjects();
1763 		ARX_SCRIPT_ResetAll(0);
1764 	}
1765 
1766 	SecondaryInventory=NULL;
1767 	TSecondaryInventory=NULL;
1768 	ARX_FOGS_Render();
1769 
1770 	if (!LOAD_N_DONT_ERASE)
1771 	{
1772 		arxtime.init();
1773 
1774 		if (!DONT_ERASE_PLAYER) ARX_PLAYER_InitPlayer();
1775 
1776 		SLID_VALUE=0.f;
1777 	}
1778 
1779 	if(!LOAD_N_DONT_ERASE) {
1780 		player.life = player.maxlife;
1781 		player.mana = player.maxmana;
1782 		if(!DONT_ERASE_PLAYER) {
1783 			ARX_PLAYER_MakeFreshHero();
1784 		}
1785 	}
1786 
1787 	InitSnapShot(fs::paths.user / "snapshot");
1788 }
1789 Vec3f LastValidPlayerPos;
1790 Vec3f	WILL_RESTORE_PLAYER_POSITION;
1791 long WILL_RESTORE_PLAYER_POSITION_FLAG=0;
1792 
FirstFrameHandling()1793 void FirstFrameHandling() {
1794 	LogDebug("FirstFrameHandling");
1795 	Vec3f trans;
1796 	FirstFrame = -1;
1797 
1798 	ARX_PARTICLES_FirstInit();
1799 	ARX_SPELLS_Init_Rects();
1800 	ARX_FOGS_TimeReset();
1801 
1802 	PROGRESS_BAR_COUNT += 2.f;
1803 	LoadLevelScreen();
1804 
1805 	FirstFrameProc();
1806 
1807 	if(FASTmse) {
1808 		FASTmse = 0;
1809 		if(LOADEDD) {
1810 			trans = Mscenepos;
1811 			player.pos = loddpos + trans;
1812 		} else {
1813 			player.pos.y += player.baseHeight();
1814 		}
1815 		PROGRESS_BAR_COUNT += 4.f;
1816 		LoadLevelScreen();
1817 	}
1818 #ifdef BUILD_EDIT_LOADSAVE
1819 	else if(mse) {
1820 		Mscenepos.x=-mse->cub.xmin-(mse->cub.xmax-mse->cub.xmin)*.5f+((float)ACTIVEBKG->Xsize*(float)ACTIVEBKG->Xdiv)*.5f;
1821 		Mscenepos.z=-mse->cub.zmin-(mse->cub.zmax-mse->cub.zmin)*.5f+((float)ACTIVEBKG->Zsize*(float)ACTIVEBKG->Zdiv)*.5f;
1822 		float t1=(float)(long)(mse->point0.x/BKG_SIZX);
1823 		float t2=(float)(long)(mse->point0.z/BKG_SIZZ);
1824 		t1=mse->point0.x-t1*BKG_SIZX;
1825 		t2=mse->point0.z-t2*BKG_SIZZ;
1826 		Mscenepos.x=(float)((long)(Mscenepos.x/BKG_SIZX))*BKG_SIZX+(float)BKG_SIZX*.5f;
1827 		Mscenepos.z=(float)((long)(Mscenepos.z/BKG_SIZZ))*BKG_SIZZ+(float)BKG_SIZZ*.5f;
1828 		mse->pos.x=Mscenepos.x=Mscenepos.x+BKG_SIZX-t1;
1829 		mse->pos.z=Mscenepos.z=Mscenepos.z+BKG_SIZZ-t2;
1830 		Mscenepos.y=mse->pos.y=-mse->cub.ymin-100.f-mse->point0.y;
1831 
1832 		if (!NO_PLAYER_POSITION_RESET)
1833 		{
1834 			player.pos.x = mse->pos.x+mse->point0.x;
1835 			player.pos.z = mse->pos.z+mse->point0.z;
1836 			player.pos.y = mse->pos.y+mse->point0.y;
1837 		}
1838 
1839 		EERIERemovePrecalcLights();
1840 
1841 		PROGRESS_BAR_COUNT+=1.f;
1842 		LoadLevelScreen();
1843 
1844 		SceneAddMultiScnToBackground(mse);
1845 
1846 		PROGRESS_BAR_COUNT+=2.f;
1847 		LoadLevelScreen();
1848 
1849 		trans = mse->pos;
1850 
1851 		ReleaseMultiScene(mse);
1852 		mse=NULL;
1853 
1854 		if(!NO_PLAYER_POSITION_RESET) {
1855 			if(LOADEDD) {
1856 				player.pos = loddpos + trans;
1857 			} else {
1858 				player.pos.y += player.baseHeight();
1859 			}
1860 		}
1861 
1862 		NO_PLAYER_POSITION_RESET=0;
1863 
1864 		PROGRESS_BAR_COUNT+=1.f;
1865 		LoadLevelScreen();
1866 	}
1867 #endif // BUILD_EDIT_LOADSAVE
1868 	else
1869 	{
1870 		PROGRESS_BAR_COUNT+=4.f;
1871 		LoadLevelScreen();
1872 	}
1873 
1874 	if (CURRENT_TORCH)
1875 	{
1876 		ARX_SOUND_PlaySFX(SND_TORCH_LOOP, NULL, 1.0F, ARX_SOUND_PLAY_LOOPED);
1877 		SHOW_TORCH=1;
1878 	}
1879 	else
1880 	{
1881 		SHOW_TORCH=0;
1882 	}
1883 
1884 	Kam = &subj;
1885 
1886 	lastteleport = player.basePosition();
1887 	subj.pos = moveto = player.pos;
1888 	mapcam.pos.x = player.pos.x;
1889 	mapcam.pos.z = player.pos.z;
1890 
1891 	subj.angle = player.angle;
1892 
1893 	RestoreLastLoadedLightning();
1894 
1895 	PROGRESS_BAR_COUNT+=1.f;
1896 	LoadLevelScreen();
1897 
1898 	if (!LOAD_N_DONT_ERASE)
1899 		SetEditMode(0);
1900 
1901 	PROGRESS_BAR_COUNT+=1.f;
1902 	LoadLevelScreen();
1903 
1904 	LOAD_N_DONT_ERASE=0;
1905 	DONT_ERASE_PLAYER=0;
1906 
1907 	PROGRESS_BAR_COUNT+=1.f;
1908 	LoadLevelScreen();
1909 
1910 	FirstFrame=0;
1911 	FRAME_COUNT=0;
1912 	PrepareIOTreatZone(1);
1913 	CURRENTLEVEL=GetLevelNumByName(LastLoadedScene.string());
1914 
1915 	if (!NO_TIME_INIT)
1916 		arxtime.init();
1917 
1918 	arxtime.update_last_frame_time();
1919 
1920 	PROGRESS_BAR_COUNT += 1.f;
1921 	LoadLevelScreen();
1922 
1923 	delete ITC.Get("presentation");
1924 	ITC.Set("presentation", NULL);
1925 
1926 	if(DONT_WANT_PLAYER_INZONE) {
1927 		player.inzone = NULL;
1928 		DONT_WANT_PLAYER_INZONE = 0;
1929 	}
1930 
1931 	PROGRESS_BAR_COUNT+=1.f;
1932 	LoadLevelScreen();
1933 
1934 	player.desiredangle.a=player.angle.a=0.f;
1935 	ARX_PLAYER_RectifyPosition();
1936 
1937 	if (entities.player())
1938 		entities.player()->_npcdata->vvpos=-99999;
1939 
1940 	SendGameReadyMsg();
1941 	PLAYER_MOUSELOOK_ON = false;
1942 	player.Interface &= ~INTER_NOTE;
1943 
1944 	if (NO_TIME_INIT)
1945 	{
1946 		arxtime.force_time_restore(FORCE_TIME_RESTORE);
1947 		arxtime.force_frame_time_restore(FORCE_TIME_RESTORE);
1948 	}
1949 	else
1950 	{
1951 		arxtime.resume();
1952 	}
1953 
1954 	long t = entities.getById("seat_stool1_0012");
1955 	if(ValidIONum(t)) {
1956 		entities[t]->ioflags |= IO_FORCEDRAW;
1957 	}
1958 
1959 	if(WILL_RESTORE_PLAYER_POSITION_FLAG) {
1960 		Entity * io = entities.player();
1961 		player.pos = WILL_RESTORE_PLAYER_POSITION;
1962 		io->pos = player.basePosition();
1963 		for(size_t i = 0; i < io->obj->vertexlist.size(); i++) {
1964 			io->obj->vertexlist3[i].v = io->obj->vertexlist[i].v + io->pos;
1965 		}
1966 		WILL_RESTORE_PLAYER_POSITION_FLAG = 0;
1967 	}
1968 
1969 	for(size_t i = 0; i < entities.size(); i++) {
1970 		if(entities[i] && (entities[i]->ioflags & IO_NPC)
1971 		   && entities[i]->_npcdata->cuts) {
1972 			ARX_NPC_ApplyCuts(entities[i]);
1973 		}
1974 	}
1975 
1976 	ResetVVPos(entities.player());
1977 
1978  PROGRESS_BAR_COUNT+=1.f;
1979  LoadLevelScreen();
1980 	LoadLevelScreen(-2);
1981 
1982 	if (	(!CheckInPolyPrecis(player.pos.x,player.pos.y,player.pos.z))
1983 		&&	(LastValidPlayerPos.x!=0.f)
1984 		&&	(LastValidPlayerPos.y!=0.f)
1985 		&&	(LastValidPlayerPos.z!=0.f)) {
1986 		player.pos = LastValidPlayerPos;
1987 	}
1988 
1989 	LastValidPlayerPos = player.pos;
1990 }
1991 
1992 //*************************************************************************************
1993 
ManageNONCombatModeAnimations()1994 void ManageNONCombatModeAnimations()
1995 {
1996 	Entity * io=entities.player();
1997 
1998 	if (!io) return;
1999 
2000 	ANIM_USE * useanim3=&io->animlayer[3];
2001 	ANIM_HANDLE ** alist=io->anims;
2002 
2003 	// FIRST SHIELD Management !
2004 	if (	(player.Current_Movement & PLAYER_LEAN_LEFT)
2005 		||	(player.Current_Movement & PLAYER_LEAN_RIGHT)			)
2006 	{
2007 	}
2008 	else if ((player.equiped[EQUIP_SLOT_SHIELD] != 0) && !BLOCK_PLAYER_CONTROLS)
2009 	{
2010 		if ( (useanim3->cur_anim==NULL)  ||
2011 			( (useanim3->cur_anim!=alist[ANIM_SHIELD_CYCLE])
2012 			&& (useanim3->cur_anim!=alist[ANIM_SHIELD_HIT])
2013 			&& (useanim3->cur_anim!=alist[ANIM_SHIELD_START]) ) )
2014 		{
2015 			AcquireLastAnim(io);
2016 			ANIM_Set(useanim3,alist[ANIM_SHIELD_START]);
2017 		}
2018 		else if ((useanim3->cur_anim==alist[ANIM_SHIELD_START])
2019 			&& (useanim3->flags & EA_ANIMEND))
2020 		{
2021 			AcquireLastAnim(io);
2022 			ANIM_Set(useanim3,alist[ANIM_SHIELD_CYCLE]);
2023 			useanim3->flags|=EA_LOOP;
2024 		}
2025 	}
2026 	else
2027 	{
2028 		if (useanim3->cur_anim==alist[ANIM_SHIELD_CYCLE])
2029 		{
2030 			AcquireLastAnim(io);
2031 			ANIM_Set(useanim3,alist[ANIM_SHIELD_END]);
2032 		}
2033 		else if ((useanim3->cur_anim==alist[ANIM_SHIELD_END])
2034 			&& (useanim3->flags & EA_ANIMEND))
2035 		{
2036 			useanim3->cur_anim=NULL;
2037 		}
2038 	}
2039 }
2040 
Player_Arrow_Count()2041 long Player_Arrow_Count() {
2042 
2043 	long count = 0;
2044 
2045 	if(player.bag) {
2046 		for(int iNbBag = 0; iNbBag < player.bag; iNbBag++) {
2047 			for(size_t j = 0; j < INVENTORY_Y; j++) {
2048 				for(size_t i = 0; i < INVENTORY_X; i++) {
2049 					Entity * io = inventory[iNbBag][i][j].io;
2050 					if(io) {
2051 						if(io->short_name() == "arrows") {
2052 							if(io->durability >= 1.f) {
2053 								count += checked_range_cast<long>(io->durability);
2054 							}
2055 						}
2056 					}
2057 				}
2058 			}
2059 		}
2060 	}
2061 
2062 	return count;
2063 }
2064 
Player_Arrow_Count_Decrease()2065 Entity * Player_Arrow_Count_Decrease() {
2066 
2067 	Entity * io = NULL;
2068 
2069 	if(player.bag) {
2070 		for(int iNbBag = 0; iNbBag < player.bag; iNbBag++) {
2071 			for(size_t j = 0; j < INVENTORY_Y; j++) {
2072 				for(size_t i = 0; i < INVENTORY_X;i++) {
2073 					Entity * ioo = inventory[iNbBag][i][j].io;
2074 					if(ioo) {
2075 						if(ioo->short_name() == "arrows") {
2076 							if(ioo->durability >= 1.f) {
2077 								if(!io) {
2078 									io = ioo;
2079 								} else if(io->durability > ioo->durability) {
2080 									io = ioo;
2081 								}
2082 							}
2083 						}
2084 					}
2085 				}
2086 			}
2087 		}
2088 	}
2089 
2090 	return io;
2091 }
2092 float GLOBAL_SLOWDOWN=1.f;
2093 
StrikeAimtime()2094 bool StrikeAimtime()
2095 {
2096 	ARX_PLAYER_Remove_Invisibility();
2097 	STRIKE_AIMTIME=float(arxtime)-(float)AimTime;
2098 	STRIKE_AIMTIME=STRIKE_AIMTIME*(1.f+(1.f-GLOBAL_SLOWDOWN));
2099 
2100 	if (STRIKE_AIMTIME>player.Full_AimTime)
2101 		STRIKE_AIMTIME=1.f;
2102 	else
2103 		STRIKE_AIMTIME=(float)STRIKE_AIMTIME/(float)player.Full_AimTime;
2104 
2105 	if (STRIKE_AIMTIME<0.1f) STRIKE_AIMTIME=0.1f;
2106 
2107 	if (STRIKE_AIMTIME>0.8f)
2108 		return true;
2109 
2110 	return false;
2111 }
2112 
strikeSpeak(Entity * io)2113 void strikeSpeak(Entity * io) {
2114 
2115 	if(!StrikeAimtime()) {
2116 		return;
2117 	}
2118 
2119 	const string * str;
2120 	long equiped = player.equiped[EQUIP_SLOT_WEAPON];
2121 	if(equiped != 0 && !entities[equiped]->strikespeech.empty()) {
2122 		str = &entities[equiped]->strikespeech;
2123 	} else if(!io->strikespeech.empty()) {
2124 		str = &io->strikespeech;
2125 	} else {
2126 		return;
2127 	}
2128 
2129 	ARX_SPEECH_AddSpeech(io, *str, ANIM_TALK_NEUTRAL, ARX_SPEECH_FLAG_NOTEXT);
2130 }
2131 
ManageCombatModeAnimations()2132 void ManageCombatModeAnimations()
2133 {
2134 	STRIKE_TIME=0;
2135 	Entity * io=entities.player();
2136 
2137 	if (!io) return;
2138 
2139 	ANIM_USE * useanim=&io->animlayer[1];
2140 
2141 	ANIM_HANDLE ** alist=io->anims;
2142 	long j;
2143 	long weapontype=ARX_EQUIPMENT_GetPlayerWeaponType();
2144 
2145 	if ((weapontype==WEAPON_BARE) && (LAST_WEAPON_TYPE!=weapontype))
2146 	{
2147 		if (useanim->cur_anim!=alist[ANIM_BARE_WAIT])
2148 		{
2149 			AcquireLastAnim(io);
2150 			ANIM_Set(useanim,alist[ANIM_BARE_WAIT]);
2151 			AimTime=0;
2152 		}
2153 	}
2154 
2155 	switch (weapontype)
2156 	{
2157 		case WEAPON_BARE:	// BARE HANDS PLAYER MANAGEMENT
2158 
2159 			if (useanim->cur_anim==alist[ANIM_BARE_WAIT])
2160 			{
2161 				AimTime=0;
2162 
2163 				if (EERIEMouseButton & 1)
2164 				{
2165 					AcquireLastAnim(io);
2166 					ANIM_Set(useanim,alist[ANIM_BARE_STRIKE_LEFT_START+CurrFightPos*3]);
2167 					io->isHit = false;
2168 				}
2169 			}
2170 
2171 			// Now go for strike cycle...
2172 			for (j=0;j<4;j++)
2173 			{
2174 				if (	(useanim->cur_anim==alist[ANIM_BARE_STRIKE_LEFT_START+j*3])
2175 					&&	(useanim->flags & EA_ANIMEND)	)
2176 				{
2177 					AcquireLastAnim(io);
2178 					ANIM_Set(useanim,alist[ANIM_BARE_STRIKE_LEFT_CYCLE+j*3]);
2179 					AimTime = (unsigned long)(arxtime);
2180 					useanim->flags|=EA_LOOP;
2181 				}
2182 				else if (	(useanim->cur_anim==alist[ANIM_BARE_STRIKE_LEFT_CYCLE+j*3])
2183 						&& !(EERIEMouseButton & 1)  )
2184 				{
2185 					AcquireLastAnim(io);
2186 					ANIM_Set(useanim,alist[ANIM_BARE_STRIKE_LEFT+j*3]);
2187 
2188 					strikeSpeak(io);
2189 
2190 					SendIOScriptEvent(io,SM_STRIKE,"bare");
2191 					PlayerWeaponBlocked=-1;
2192 					CurrFightPos=0;
2193 					AimTime=0;
2194 				}
2195 				else if (useanim->cur_anim==alist[ANIM_BARE_STRIKE_LEFT+j*3])
2196 				{
2197 					if (useanim->flags & EA_ANIMEND)
2198 					{
2199 						AcquireLastAnim(io);
2200 						ANIM_Set(useanim,alist[ANIM_BARE_WAIT]);
2201 						useanim->flags|=EA_LOOP;
2202 						CurrFightPos=0;
2203 						AimTime = (unsigned long)(arxtime);
2204 						PlayerWeaponBlocked=-1;
2205 					}
2206 					else if ((useanim->ctime > useanim->cur_anim->anims[useanim->altidx_cur]->anim_time * 0.2f)
2207 								&&	(useanim->ctime < useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.8f)
2208 								&&	(PlayerWeaponBlocked==-1) )
2209 						{
2210 							if (useanim->cur_anim==alist[ANIM_BARE_STRIKE_LEFT])
2211 							{
2212 								STRIKE_TIME=1;
2213 							long id = io->obj->fastaccess.left_attach;
2214 
2215 								if (id!=-1)
2216 								{
2217 									EERIE_SPHERE sphere;
2218 									sphere.origin = io->obj->vertexlist3[id].v;
2219 									sphere.radius = 25.f;
2220 
2221 									if (FistParticles & 2) sphere.radius*=2.f;
2222 
2223 									long num;
2224 
2225 									if (CheckAnythingInSphere(&sphere,0,0,&num))
2226 									{
2227 										float dmgs=(player.Full_damages+1)*STRIKE_AIMTIME;
2228 
2229 										if (FistParticles & 2) dmgs*=1.5f;
2230 
2231 										if (ARX_DAMAGES_TryToDoDamage(&io->obj->vertexlist3[id].v,dmgs,40,0))
2232 										{
2233 											if (FistParticles & 2)
2234 												ARX_SOUND_PlaySFX(SND_SPELL_LIGHTNING_START, &io->obj->vertexlist3[id].v);
2235 
2236 											PlayerWeaponBlocked=useanim->ctime;
2237 										}
2238 
2239 										{
2240 										ARX_PARTICLES_Spawn_Spark(&sphere.origin, dmgs, 2);
2241 
2242 											if (ValidIONum(num))
2243 											{
2244 												ARX_SOUND_PlayCollision(entities[num]->material,MATERIAL_FLESH, 1.f, 1.f, &sphere.origin, NULL);
2245 											}
2246 										}
2247 
2248 									}
2249 								}
2250 							}
2251 							else  // Strike Right
2252 							{
2253 								STRIKE_TIME=1;
2254 							long id = io->obj->fastaccess.primary_attach;
2255 
2256 								if (id!=-1)
2257 								{
2258 									EERIE_SPHERE sphere;
2259 									sphere.origin = io->obj->vertexlist3[id].v;
2260 									sphere.radius = 25.f;
2261 
2262 									if (FistParticles & 2) sphere.radius*=2.f;
2263 
2264 									long num;
2265 
2266 									if (CheckAnythingInSphere(&sphere,0,0,&num))
2267 									{
2268 										float dmgs=(player.Full_damages+1)*STRIKE_AIMTIME;
2269 
2270 										if (FistParticles & 2) dmgs*=1.5f;
2271 
2272 										if (ARX_DAMAGES_TryToDoDamage(&io->obj->vertexlist3[id].v,dmgs,40,0))
2273 										{
2274 											if (FistParticles & 2)
2275 												ARX_SOUND_PlaySFX(SND_SPELL_LIGHTNING_START, &io->obj->vertexlist3[id].v);
2276 
2277 											PlayerWeaponBlocked=useanim->ctime;
2278 										}
2279 
2280 										{
2281 										ARX_PARTICLES_Spawn_Spark(&sphere.origin, dmgs, 2);
2282 
2283 											if (ValidIONum(num))
2284 											{
2285 												ARX_SOUND_PlayCollision(entities[num]->material,MATERIAL_FLESH, 1.f, 1.f, &sphere.origin, NULL);
2286 											}
2287 										}
2288 
2289 									}
2290 								}
2291 							}
2292 						}
2293 				}
2294 			}
2295 
2296 		break;
2297 		case WEAPON_DAGGER: // DAGGER PLAYER MANAGEMENT
2298 			// Waiting and receiving Strike Impulse
2299 			if (useanim->cur_anim==alist[ANIM_DAGGER_WAIT])
2300 			{
2301 				AimTime = 0;
2302 
2303 				if (EERIEMouseButton & 1)
2304 				{
2305 					AcquireLastAnim(io);
2306 					ANIM_Set(useanim,alist[ANIM_DAGGER_STRIKE_LEFT_START+CurrFightPos*3]);
2307 					io->isHit = false;
2308 				}
2309 			}
2310 
2311 			// Now go for strike cycle...
2312 			for (j=0;j<4;j++)
2313 			{
2314 				if ((useanim->cur_anim==alist[ANIM_DAGGER_STRIKE_LEFT_START+j*3])&& (useanim->flags & EA_ANIMEND))
2315 				{
2316 					AcquireLastAnim(io);
2317 					ANIM_Set(useanim,alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE+j*3]);
2318 					AimTime = (unsigned long)(arxtime);
2319 					useanim->flags|=EA_LOOP;
2320 				}
2321 				else if ((useanim->cur_anim==alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE+j*3])
2322 						&& !(EERIEMouseButton & 1))
2323 				{
2324 					AcquireLastAnim(io);
2325 					ANIM_Set(useanim,alist[ANIM_DAGGER_STRIKE_LEFT+j*3]);
2326 
2327 					strikeSpeak(io);
2328 
2329 					SendIOScriptEvent(io,SM_STRIKE,"dagger");
2330 					CurrFightPos=0;
2331 					AimTime=0;
2332 				}
2333 				else if (useanim->cur_anim==alist[ANIM_DAGGER_STRIKE_LEFT+j*3])
2334 				{
2335 					if (	(useanim->ctime > useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.3f)
2336 						&&	(useanim->ctime < useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.7f))
2337 					{
2338 						STRIKE_TIME=1;
2339 
2340 						if ((PlayerWeaponBlocked==-1)
2341 						&& (ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,0)))
2342 						{
2343 							PlayerWeaponBlocked=useanim->ctime;
2344 						}
2345 					}
2346 
2347 					if (useanim->flags & EA_ANIMEND)
2348 					{
2349 						AcquireLastAnim(io);
2350 						ANIM_Set(useanim,alist[ANIM_DAGGER_WAIT]);
2351 						useanim->flags&=~(EA_PAUSED | EA_REVERSE);
2352 						useanim->flags|=EA_LOOP;
2353 						CurrFightPos=0;
2354 						AimTime = (unsigned long)(arxtime);
2355 						PlayerWeaponBlocked=-1;
2356 					}
2357 
2358 					if ((PlayerWeaponBlocked!=-1)
2359 						&& (useanim->ctime<useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.9f))
2360 						ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,1);
2361 
2362 				}
2363 			}
2364 
2365 		break;
2366 		case WEAPON_1H: // 1HANDED PLAYER MANAGEMENT
2367 			// Waiting and Received Strike Impulse
2368 			if (useanim->cur_anim==alist[ANIM_1H_WAIT])
2369 			{
2370 				AimTime = 0;
2371 
2372 				if (EERIEMouseButton & 1)
2373 				{
2374 					AcquireLastAnim(io);
2375 					ANIM_Set(useanim,alist[ANIM_1H_STRIKE_LEFT_START+CurrFightPos*3]);
2376 					io->isHit = false;
2377 				}
2378 			}
2379 
2380 			// Now go for strike cycle...
2381 			for (j=0;j<4;j++)
2382 			{
2383 				if ((useanim->cur_anim==alist[ANIM_1H_STRIKE_LEFT_START+j*3])&& (useanim->flags & EA_ANIMEND))
2384 				{
2385 					AcquireLastAnim(io);
2386 					ANIM_Set(useanim,alist[ANIM_1H_STRIKE_LEFT_CYCLE+j*3]);
2387 					AimTime = (unsigned long)(arxtime);
2388 					useanim->flags|=EA_LOOP;
2389 				}
2390 				else if ((useanim->cur_anim==alist[ANIM_1H_STRIKE_LEFT_CYCLE+j*3])
2391 						 && !(EERIEMouseButton & 1))
2392 				{
2393 					AcquireLastAnim(io);
2394 					ANIM_Set(useanim,alist[ANIM_1H_STRIKE_LEFT+j*3]);
2395 
2396 					strikeSpeak(io);
2397 
2398 					SendIOScriptEvent(io,SM_STRIKE,"1h");
2399 					CurrFightPos=0;
2400 					AimTime=0;
2401 				}
2402 				else if (useanim->cur_anim==alist[ANIM_1H_STRIKE_LEFT+j*3])
2403 				{
2404 						if ((useanim->ctime > useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.3f)
2405 							&& (useanim->ctime < useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.7f))
2406 						{
2407 							STRIKE_TIME=1;
2408 
2409 							if ((PlayerWeaponBlocked==-1)
2410 								&& (ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,0)) )
2411 							{
2412 								PlayerWeaponBlocked=useanim->ctime;
2413 							}
2414 						}
2415 
2416 						if (useanim->flags & EA_ANIMEND)
2417 						{
2418 							AcquireLastAnim(io);
2419 							ANIM_Set(useanim,alist[ANIM_1H_WAIT]);
2420 							useanim->flags&=~(EA_PAUSED | EA_REVERSE);
2421 							useanim->flags|=EA_LOOP;
2422 							CurrFightPos=0;
2423 							AimTime=0;
2424 							PlayerWeaponBlocked=-1;
2425 						}
2426 
2427 						if ((PlayerWeaponBlocked!=-1)
2428 							&& (useanim->ctime<useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.9f))
2429 							ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,1);
2430 
2431 				}
2432 			}
2433 
2434 		break;
2435 		case WEAPON_2H: // 2HANDED PLAYER MANAGEMENT
2436 			// Waiting and Receiving Strike Impulse
2437 			if (useanim->cur_anim==alist[ANIM_2H_WAIT])
2438 			{
2439 				AimTime = 0;
2440 
2441 				if (EERIEMouseButton & 1)
2442 				{
2443 					AcquireLastAnim(io);
2444 					ANIM_Set(useanim,alist[ANIM_2H_STRIKE_LEFT_START+CurrFightPos*3]);
2445 
2446 					io->isHit = false;
2447 				}
2448 			}
2449 
2450 			// Now go for strike cycle...
2451 			for (j=0;j<4;j++)
2452 			{
2453 				if (	(useanim->cur_anim==alist[ANIM_2H_STRIKE_LEFT_START+j*3])
2454 					&&	(useanim->flags & EA_ANIMEND))
2455 				{
2456 					AcquireLastAnim(io);
2457 					ANIM_Set(useanim,alist[ANIM_2H_STRIKE_LEFT_CYCLE+j*3]);
2458 					AimTime = (unsigned long)(arxtime);
2459 					useanim->flags|=EA_LOOP;
2460 				}
2461 				else if (	(useanim->cur_anim==alist[ANIM_2H_STRIKE_LEFT_CYCLE+j*3])
2462 						&&	!(EERIEMouseButton & 1) )
2463 				{
2464 
2465 					AcquireLastAnim(io);
2466 					ANIM_Set(useanim,alist[ANIM_2H_STRIKE_LEFT+j*3]);
2467 
2468 					strikeSpeak(io);
2469 
2470 					SendIOScriptEvent(io,SM_STRIKE,"2h");
2471 					CurrFightPos=0;
2472 					AimTime=0;
2473 				}
2474 				else if (useanim->cur_anim==alist[ANIM_2H_STRIKE_LEFT+j*3])
2475 				{
2476 						if ((useanim->ctime > useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.3f)
2477 							&& (useanim->ctime < useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.7f))
2478 						{
2479 							STRIKE_TIME=1;
2480 
2481 							if ((PlayerWeaponBlocked==-1)
2482 								&& (ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,0)) )
2483 							{
2484 								PlayerWeaponBlocked=useanim->ctime;
2485 							}
2486 						}
2487 
2488 						if (useanim->flags & EA_ANIMEND)
2489 						{
2490 							AcquireLastAnim(io);
2491 							ANIM_Set(useanim,alist[ANIM_2H_WAIT]);
2492 							useanim->flags&=~(EA_PAUSED | EA_REVERSE);
2493 							useanim->flags|=EA_LOOP;
2494 							CurrFightPos=0;
2495 							AimTime=0;
2496 							PlayerWeaponBlocked=-1;
2497 						}
2498 
2499 						if ((PlayerWeaponBlocked!=-1)
2500 							&& (useanim->ctime<useanim->cur_anim->anims[useanim->altidx_cur]->anim_time*0.9f))
2501 							ARX_EQUIPMENT_Strike_Check(io,entities[player.equiped[EQUIP_SLOT_WEAPON]],STRIKE_AIMTIME,1);
2502 
2503 				}
2504 			}
2505 
2506 		break;
2507 
2508 		case WEAPON_BOW: // MISSILE PLAYER MANAGEMENT
2509 
2510 			if(useanim->cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) {
2511 				if (GLOBAL_SLOWDOWN!=1.f)
2512 					BOW_FOCAL+=Original_framedelay;
2513 				else
2514 					BOW_FOCAL += framedelay;
2515 
2516 				if (BOW_FOCAL>710) BOW_FOCAL=710;
2517 			}
2518 
2519 			// Waiting and Receiving Strike Impulse
2520 			if (useanim->cur_anim==alist[ANIM_MISSILE_WAIT])
2521 			{
2522 				AimTime = (unsigned long)(arxtime);
2523 
2524 				if ((EERIEMouseButton & 1) && (Player_Arrow_Count()>0))
2525 				{
2526 					AcquireLastAnim(io);
2527 					ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_PART_1]);
2528 					io->isHit = false;
2529 				}
2530 			}
2531 
2532 			if ((useanim->cur_anim==alist[ANIM_MISSILE_STRIKE_PART_1])&& (useanim->flags & EA_ANIMEND))
2533 			{
2534 				AimTime = 0;
2535 				AcquireLastAnim(io);
2536 				ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_PART_2]);
2537 
2538 				EERIE_LINKEDOBJ_LinkObjectToObject(io->obj, arrowobj, "left_attach", "attach", NULL);
2539 
2540 			}
2541 
2542 			// Now go for strike cycle...
2543 			if ((useanim->cur_anim==alist[ANIM_MISSILE_STRIKE_PART_2])&& (useanim->flags & EA_ANIMEND))
2544 			{
2545 				AcquireLastAnim(io);
2546 				ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_CYCLE]);
2547 				AimTime = (unsigned long)(arxtime);
2548 
2549 				useanim->flags|=EA_LOOP;
2550 			}
2551 			else if ((useanim->cur_anim==alist[ANIM_MISSILE_STRIKE_CYCLE])
2552 				&& !(EERIEMouseButton & 1))
2553 			{
2554 
2555 				EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
2556 				AcquireLastAnim(io);
2557 				ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE]);
2558 				SendIOScriptEvent(io,SM_STRIKE,"bow");
2559 				StrikeAimtime();
2560 				STRIKE_AIMTIME=(float)(BOW_FOCAL)/710.f;
2561 				Entity * ioo=Player_Arrow_Count_Decrease();
2562 				float poisonous=0.f;
2563 
2564 				if (ioo)
2565 				{
2566 					if (ioo->poisonous_count>0)
2567 					{
2568 						poisonous=ioo->poisonous;
2569 						ioo->poisonous_count--;
2570 
2571 						if (ioo->poisonous_count<=0)
2572 							ioo->poisonous=0;
2573 					}
2574 					else poisonous=ioo->poisonous;
2575 
2576 					ARX_DAMAGES_DurabilityLoss(ioo,1.f);
2577 
2578 					if (ValidIOAddress(ioo))
2579 					{
2580 						if (ioo->durability<=0.f)
2581 							ARX_INTERACTIVE_DestroyIO(ioo);
2582 					}
2583 				}
2584 
2585 				PlayerLaunchArrow(STRIKE_AIMTIME,poisonous);
2586 				AimTime=0;
2587 			}
2588 			else if (useanim->cur_anim==alist[ANIM_MISSILE_STRIKE])
2589 			{
2590 				BOW_FOCAL-=Original_framedelay;
2591 
2592 				if (BOW_FOCAL<0) BOW_FOCAL=0;
2593 
2594 				if (useanim->flags & EA_ANIMEND)
2595 				{
2596 					BOW_FOCAL=0;
2597 					AcquireLastAnim(io);
2598 					ANIM_Set(useanim,alist[ANIM_MISSILE_WAIT]);
2599 					useanim->flags|=EA_LOOP;
2600 					AimTime=0;
2601 					PlayerWeaponBlocked=-1;
2602 					EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
2603 				}
2604 			}
2605 
2606 		break;
2607 	}
2608 
2609 	LAST_WEAPON_TYPE=weapontype;
2610 }
ManageCombatModeAnimationsEND()2611 void ManageCombatModeAnimationsEND()
2612 {
2613 	Entity * io=entities.player();
2614 	ANIM_USE * useanim=&io->animlayer[1];
2615 
2616 	ANIM_USE * useanim3=&io->animlayer[3];
2617 	ANIM_HANDLE ** alist=io->anims;
2618 
2619 	if (	(useanim->cur_anim)
2620 		&&(		(useanim->cur_anim==alist[ANIM_BARE_READY])
2621 			||	(useanim->cur_anim==alist[ANIM_DAGGER_READY_PART_2])
2622 			||	(useanim->cur_anim==alist[ANIM_DAGGER_READY_PART_1])
2623 			||	(useanim->cur_anim==alist[ANIM_1H_READY_PART_2])
2624 			||	(useanim->cur_anim==alist[ANIM_1H_READY_PART_1])
2625 			||	(useanim->cur_anim==alist[ANIM_2H_READY_PART_2])
2626 			||	(useanim->cur_anim==alist[ANIM_2H_READY_PART_1])
2627 			||	(useanim->cur_anim==alist[ANIM_MISSILE_READY_PART_1])
2628 			||	(useanim->cur_anim==alist[ANIM_MISSILE_READY_PART_2])	)
2629 			)
2630 		AimTime = (unsigned long)(arxtime);
2631 
2632 	if (useanim->flags & EA_ANIMEND)
2633 	{
2634 		long weapontype=ARX_EQUIPMENT_GetPlayerWeaponType();
2635 
2636 		if (useanim->cur_anim &&
2637 			(	(useanim->cur_anim==io->anims[ANIM_BARE_UNREADY])
2638 			||	(useanim->cur_anim==io->anims[ANIM_DAGGER_UNREADY_PART_2])
2639 			||	(useanim->cur_anim==io->anims[ANIM_1H_UNREADY_PART_2])
2640 			||	(useanim->cur_anim==io->anims[ANIM_2H_UNREADY_PART_2])
2641 			||	(useanim->cur_anim==io->anims[ANIM_MISSILE_UNREADY_PART_2])	)	)
2642 		{
2643 			io->_npcdata->ex_rotate->flags|=EXTRA_ROTATE_REALISTIC;
2644 			AcquireLastAnim(io);
2645 			useanim->cur_anim=NULL;
2646 		}
2647 
2648 		switch (weapontype)
2649 		{
2650 			case WEAPON_BARE:
2651 
2652 				// Is Weapon Ready ? In this case go to Fight Wait anim
2653 				if (useanim->cur_anim==alist[ANIM_BARE_READY])
2654 				{
2655 
2656 					AcquireLastAnim(io);
2657 
2658 					if (player.Interface & INTER_NO_STRIKE)
2659 					{
2660 						player.Interface&=~INTER_NO_STRIKE;
2661 						ANIM_Set(useanim,alist[ANIM_BARE_WAIT]);
2662 						useanim->flags|=EA_LOOP;
2663 					}
2664 					else
2665 						ANIM_Set(useanim,alist[ANIM_BARE_STRIKE_LEFT_START+CurrFightPos*3]);
2666 
2667 					AimTime = (unsigned long)(arxtime);
2668 					io->isHit = false;
2669 				}
2670 
2671 			break;
2672 			case WEAPON_DAGGER:
2673 
2674 				// DAGGER ANIMS end
2675 				if (alist[ANIM_DAGGER_READY_PART_1])
2676 				{
2677 					if (useanim->cur_anim==alist[ANIM_DAGGER_READY_PART_1])
2678 					{
2679 						AcquireLastAnim(io);
2680 						ARX_EQUIPMENT_AttachPlayerWeaponToHand();
2681 						ANIM_Set(useanim,alist[ANIM_DAGGER_READY_PART_2]);
2682 					}
2683 					else if (useanim->cur_anim==alist[ANIM_DAGGER_READY_PART_2])
2684 					{
2685 						AcquireLastAnim(io);
2686 
2687 						if (player.Interface & INTER_NO_STRIKE)
2688 						{
2689 							player.Interface&=~INTER_NO_STRIKE;
2690 							ANIM_Set(useanim,alist[ANIM_DAGGER_WAIT]);
2691 							useanim->flags|=EA_LOOP;
2692 						}
2693 						else
2694 							ANIM_Set(useanim,alist[ANIM_DAGGER_STRIKE_LEFT_START+CurrFightPos*3]);
2695 
2696 						AimTime = (unsigned long)(arxtime);
2697 						io->isHit = false;
2698 					}
2699 					else if (useanim->cur_anim==alist[ANIM_DAGGER_UNREADY_PART_1])
2700 					{
2701 						AcquireLastAnim(io);
2702 						ARX_EQUIPMENT_AttachPlayerWeaponToBack();
2703 						ANIM_Set(useanim,alist[ANIM_DAGGER_UNREADY_PART_2]);
2704 					}
2705 				}
2706 
2707 			break;
2708 			case WEAPON_1H:	// 1H ANIMS end
2709 
2710 				if (alist[ANIM_1H_READY_PART_1]!=NULL)
2711 				{
2712 					if (useanim->cur_anim==alist[ANIM_1H_READY_PART_1])
2713 					{
2714 						AcquireLastAnim(io);
2715 						ARX_EQUIPMENT_AttachPlayerWeaponToHand();
2716 						ANIM_Set(useanim,alist[ANIM_1H_READY_PART_2]);
2717 					}
2718 					else if (useanim->cur_anim==alist[ANIM_1H_READY_PART_2])
2719 					{
2720 						AcquireLastAnim(io);
2721 
2722 						if (player.Interface & INTER_NO_STRIKE)
2723 						{
2724 							player.Interface&=~INTER_NO_STRIKE;
2725 							ANIM_Set(useanim,alist[ANIM_1H_WAIT]);
2726 							useanim->flags|=EA_LOOP;
2727 						}
2728 						else
2729 						ANIM_Set(useanim,alist[ANIM_1H_STRIKE_LEFT_START+CurrFightPos*3]);
2730 
2731 						AimTime = (unsigned long)(arxtime);
2732 						io->isHit = false;
2733 					}
2734 					else if (useanim->cur_anim==alist[ANIM_1H_UNREADY_PART_1])
2735 					{
2736 						AcquireLastAnim(io);
2737 						ARX_EQUIPMENT_AttachPlayerWeaponToBack();
2738 						ANIM_Set(useanim,alist[ANIM_1H_UNREADY_PART_2]);
2739 					}
2740 				}
2741 
2742 			break;
2743 			case WEAPON_2H:	// 2H ANIMS end
2744 
2745 				if (alist[ANIM_2H_READY_PART_1])
2746 				{
2747 					if (useanim->cur_anim==alist[ANIM_2H_READY_PART_1])
2748 					{
2749 						AcquireLastAnim(io);
2750 						ARX_EQUIPMENT_AttachPlayerWeaponToHand();
2751 						ANIM_Set(useanim,alist[ANIM_2H_READY_PART_2]);
2752 					}
2753 					else if (useanim->cur_anim==alist[ANIM_2H_READY_PART_2])
2754 					{
2755 						AcquireLastAnim(io);
2756 
2757 						if (player.Interface & INTER_NO_STRIKE)
2758 						{
2759 							player.Interface&=~INTER_NO_STRIKE;
2760 							ANIM_Set(useanim,alist[ANIM_2H_WAIT]);
2761 							useanim->flags|=EA_LOOP;
2762 						}
2763 						else
2764 							ANIM_Set(useanim,alist[ANIM_2H_STRIKE_LEFT_START+CurrFightPos*3]);
2765 
2766 						AimTime = (unsigned long)(arxtime);
2767 						io->isHit = false;
2768 					}
2769 					else if (useanim->cur_anim==alist[ANIM_2H_UNREADY_PART_1])
2770 					{
2771 						AcquireLastAnim(io);
2772 						ARX_EQUIPMENT_AttachPlayerWeaponToBack();
2773 						ANIM_Set(useanim,alist[ANIM_2H_UNREADY_PART_2]);
2774 					}
2775 				}
2776 
2777 			break;
2778 			case WEAPON_BOW:// MISSILE Weapon ANIMS end
2779 
2780 				if (alist[ANIM_MISSILE_READY_PART_1])
2781 				{
2782 					if (useanim->cur_anim==alist[ANIM_MISSILE_READY_PART_1])
2783 					{
2784 						AcquireLastAnim(io);
2785 						ARX_EQUIPMENT_AttachPlayerWeaponToHand();
2786 						ANIM_Set(useanim,alist[ANIM_MISSILE_READY_PART_2]);
2787 					}
2788 					else if (useanim->cur_anim==alist[ANIM_MISSILE_READY_PART_2])
2789 					{
2790 						if (Player_Arrow_Count()>0)
2791 						{
2792 							AcquireLastAnim(io);
2793 
2794 							if (player.Interface & INTER_NO_STRIKE)
2795 							{
2796 								player.Interface&=~INTER_NO_STRIKE;
2797 								ANIM_Set(useanim,alist[ANIM_MISSILE_WAIT]);
2798 								useanim->flags|=EA_LOOP;
2799 							}
2800 							else
2801 								ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_PART_1]);
2802 
2803 							io->isHit = false;
2804 						}
2805 						else
2806 						{
2807 							AcquireLastAnim(io);
2808 							ANIM_Set(useanim,alist[ANIM_MISSILE_WAIT]);
2809 						}
2810 
2811 						EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj);
2812 					}
2813 					else if (useanim->cur_anim==alist[ANIM_MISSILE_STRIKE_PART_1])
2814 					{
2815 						ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_PART_2]);
2816 					}
2817 					else if (useanim->cur_anim==alist[ANIM_MISSILE_STRIKE_PART_2])
2818 					{
2819 						ANIM_Set(useanim,alist[ANIM_MISSILE_STRIKE_CYCLE]);
2820 					}
2821 					else if (useanim->cur_anim==alist[ANIM_MISSILE_UNREADY_PART_1])
2822 					{
2823 						AcquireLastAnim(io);
2824 						ARX_EQUIPMENT_AttachPlayerWeaponToBack();
2825 						ANIM_Set(useanim,alist[ANIM_MISSILE_UNREADY_PART_2]);
2826 					}
2827 				}
2828 
2829 			break;
2830 		}
2831 
2832 		// Spell casting anims
2833 		if ((alist[ANIM_CAST]) && (useanim->cur_anim==alist[ANIM_CAST]))
2834 		{
2835 			AcquireLastAnim(io);
2836 
2837 			if (alist[ANIM_CAST_END])
2838 				ANIM_Set(useanim,alist[ANIM_CAST_END]);
2839 		}
2840 		else if ((alist[ANIM_CAST_END]) && (useanim->cur_anim==alist[ANIM_CAST_END]))
2841 		{
2842 			AcquireLastAnim(io);
2843 			useanim->cur_anim=NULL;
2844 			player.doingmagic=0;
2845 
2846 			if (WILLRETURNTOCOMBATMODE)
2847 			{
2848 				player.Interface|=INTER_COMBATMODE;
2849 				player.Interface|=INTER_NO_STRIKE;
2850 
2851 				ARX_EQUIPMENT_LaunchPlayerReadyWeapon();
2852 				WILLRETURNTOCOMBATMODE=0;
2853 			}
2854 		}
2855 	}
2856 
2857 	// Is the shield off ?
2858 	if (useanim3->flags & EA_ANIMEND)
2859 	{
2860 		if ((io->anims[ANIM_SHIELD_END]) && (useanim3->cur_anim==io->anims[ANIM_SHIELD_END]))
2861 		{
2862 			AcquireLastAnim(io);
2863 			useanim3->cur_anim=NULL;
2864 		}
2865 	}
2866 }
2867 
2868 float LAST_FADEVALUE=1.f;
ManageFade()2869 void ManageFade()
2870 {
2871 	float tim = (arxtime.get_updated() - (float)FADESTART);
2872 
2873 	if (tim<=0.f) return;
2874 
2875 	float Visibility=tim/(float)FADEDURATION;
2876 
2877 	if (FADEDIR>0) Visibility=1.f-Visibility;
2878 
2879 	if (Visibility>1.f) Visibility=1.f;
2880 
2881 	if(Visibility < 0.f) {
2882 		FADEDIR = 0;
2883 		return;
2884 	}
2885 
2886 	LAST_FADEVALUE=Visibility;
2887 	GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
2888 	GRenderer->SetRenderState(Renderer::DepthWrite, false);
2889 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
2890 
2891 	EERIEDrawBitmap(0.f,0.f, (float)DANAESIZX, (float)DANAESIZY, 0.0001f, NULL, Color::gray(Visibility));
2892 
2893 	GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
2894 	float col=Visibility;
2895 	EERIEDrawBitmap(0.f,0.f,(float)DANAESIZX,(float)DANAESIZY,0.0001f,
2896 	                NULL, Color(col * FADECOLOR.r, col * FADECOLOR.g, col * FADECOLOR.b));
2897 	GRenderer->SetRenderState(Renderer::AlphaBlending, false);
2898 	GRenderer->SetRenderState(Renderer::DepthWrite, true);
2899 }
2900 
2901 extern long cur_mr;
2902 static TextureContainer * Mr_tc = NULL;
2903 
CheckMr()2904 void CheckMr()
2905 {
2906 	if (cur_mr==3)
2907 	{
2908 		if (GRenderer && Mr_tc)
2909 		{
2910 			EERIEDrawBitmap(DANAESIZX-(128.f*Xratio), 0.f, (float)128*Xratio, (float)128*Yratio,0.0001f,
2911 			                Mr_tc, Color::gray(0.5f + PULSATE * (1.0f/10)));
2912 		}
2913 		else
2914 		{
2915 			Mr_tc=TextureContainer::LoadUI("graph/particles/(fx)_mr");
2916 		}
2917 	}
2918 }
DrawImproveVisionInterface()2919 void DrawImproveVisionInterface()
2920 {
2921 	if(ombrignon)
2922 	{
2923 		float mod = 0.6f + PULSATE * 0.35f;
2924 		EERIEDrawBitmap(0.f,0.f,(float)DANAESIZX,(float)DANAESIZY,0.0001f, ombrignon, Color3f((0.5f+PULSATE*( 1.0f / 10 ))*mod,0.f,0.f).to<u8>());
2925 	}
2926 }
2927 
2928 float MagicSightFader=0.f;
DrawMagicSightInterface()2929 void DrawMagicSightInterface()
2930 {
2931 	if (eyeball.exist==1) return;
2932 
2933 	if (Flying_Eye)
2934 	{
2935 		GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
2936 		float col=(0.75f+PULSATE*( 1.0f / 20 ));
2937 
2938 		if (col>1.f) col=1.f;
2939 
2940 		if (eyeball.exist<0)
2941 		{
2942 			col=(float)(-eyeball.exist)*( 1.0f / 100 );
2943 		}
2944 		else if (eyeball.exist>2)
2945 		{
2946 			col = 1.f - eyeball.size.x;
2947 		}
2948 
2949 		EERIEDrawBitmap(0.f, 0.f, (float)DANAESIZX, (float)DANAESIZY, 0.0001f, Flying_Eye, Color::gray(col));
2950 
2951 		if (MagicSightFader>0.f)
2952 		{
2953 			col=MagicSightFader;
2954 			EERIEDrawBitmap(0.f, 0.f, (float)DANAESIZX, (float)DANAESIZY, 0.0001f, NULL, Color::gray(col));
2955 			MagicSightFader-=Original_framedelay*( 1.0f / 400 );
2956 
2957 			if (MagicSightFader<0.f)
2958 				MagicSightFader=0.f;
2959 		}
2960 
2961 		GRenderer->SetBlendFunc(Renderer::BlendOne, Renderer::BlendOne);
2962 	}
2963 }
2964 
2965 //*************************************************************************************
2966 
RenderAllNodes()2967 void RenderAllNodes() {
2968 
2969 	Anglef angle(Anglef::ZERO);
2970 	float xx, yy;
2971 
2972 	GRenderer->SetRenderState(Renderer::AlphaBlending, false);
2973 
2974 	for(long i=0;i<nodes.nbmax;i++)
2975 	{
2976 		if (nodes.nodes[i].exist)
2977 		{
2978 
2979 			DrawEERIEInter(nodeobj,
2980 				&angle,&nodes.nodes[i].pos,NULL);
2981 			nodes.nodes[i].bboxmin.x=(short)BBOXMIN.x;
2982 			nodes.nodes[i].bboxmin.y=(short)BBOXMIN.y;
2983 			nodes.nodes[i].bboxmax.x=(short)BBOXMAX.x;
2984 			nodes.nodes[i].bboxmax.y=(short)BBOXMAX.y;
2985 
2986 			if ((nodeobj->vertexlist[nodeobj->origin].vert.p.z>0.f) && (nodeobj->vertexlist[nodeobj->origin].vert.p.z<0.9f))
2987 			{
2988 				xx=nodeobj->vertexlist[nodeobj->origin].vert.p.x-40.f;
2989 				yy=nodeobj->vertexlist[nodeobj->origin].vert.p.y-40.f;
2990 				ARX_TEXT_Draw(hFontInBook, xx, yy, nodes.nodes[i].UName, Color::yellow); //font
2991 			}
2992 
2993 			if(nodes.nodes[i].selected) {
2994 				EERIEDraw2DLine(nodes.nodes[i].bboxmin.x, nodes.nodes[i].bboxmin.y, nodes.nodes[i].bboxmax.x, nodes.nodes[i].bboxmin.y, 0.01f, Color::yellow);
2995 				EERIEDraw2DLine(nodes.nodes[i].bboxmax.x, nodes.nodes[i].bboxmin.y, nodes.nodes[i].bboxmax.x, nodes.nodes[i].bboxmax.y, 0.01f, Color::yellow);
2996 				EERIEDraw2DLine(nodes.nodes[i].bboxmax.x, nodes.nodes[i].bboxmax.y, nodes.nodes[i].bboxmin.x, nodes.nodes[i].bboxmax.y, 0.01f, Color::yellow);
2997 				EERIEDraw2DLine(nodes.nodes[i].bboxmin.x, nodes.nodes[i].bboxmax.y, nodes.nodes[i].bboxmin.x, nodes.nodes[i].bboxmin.y, 0.01f, Color::yellow);
2998 			}
2999 
3000 			for(size_t j = 0; j < MAX_LINKS; j++) {
3001 				if(nodes.nodes[i].link[j]!=-1) {
3002 					EERIEDrawTrue3DLine(nodes.nodes[i].pos, nodes.nodes[nodes.nodes[i].link[j]].pos, Color::green);
3003 				}
3004 			}
3005 		}
3006 	}
3007 }
3008 
AddQuakeFX(float intensity,float duration,float period,long flags)3009 void AddQuakeFX(float intensity,float duration,float period,long flags)
3010 {
3011 	if (QuakeFx.intensity>0.f)
3012 	{
3013 		QuakeFx.intensity+=intensity;
3014 
3015 		QuakeFx.duration+=(unsigned long)duration;
3016 		QuakeFx.frequency+=period;
3017 		QuakeFx.frequency*=.5f;
3018 		QuakeFx.flags|=flags;
3019 
3020 		if (flags & 1)
3021 			ARX_SOUND_PlaySFX(SND_QUAKE, NULL, 1.0F - 0.5F * QuakeFx.intensity);
3022 	}
3023 	else
3024 	{
3025 		QuakeFx.intensity=intensity;
3026 
3027 		QuakeFx.start = checked_range_cast<unsigned long>(arxtime.get_frame_time());
3028 
3029 		QuakeFx.duration=(unsigned long)duration;
3030 		QuakeFx.frequency=period;
3031 		QuakeFx.flags=flags;
3032 
3033 		if (flags & 1)
3034 			ARX_SOUND_PlaySFX(SND_QUAKE, NULL, 1.0F - 0.5F * QuakeFx.intensity);
3035 	}
3036 
3037 	if (!(flags & 1))
3038 	{
3039 		if (QuakeFx.duration>1500) QuakeFx.duration=1500;
3040 
3041 		if (QuakeFx.intensity>220) QuakeFx.intensity=220;
3042 	}
3043 }
ManageQuakeFX()3044 void ManageQuakeFX()
3045 {
3046 	if (QuakeFx.intensity>0.f)
3047 	{
3048 		float tim=(float)arxtime.get_frame_time()-(float)QuakeFx.start;
3049 
3050 		if (tim >= QuakeFx.duration)
3051 		{
3052 			QuakeFx.intensity=0.f;
3053 			return;
3054 		}
3055 
3056 		float itmod=1.f-(tim/QuakeFx.duration);
3057 		float periodicity=EEsin((float)arxtime.get_frame_time()*QuakeFx.frequency*( 1.0f / 100 ));
3058 
3059 		if ((periodicity>0.5f) && (QuakeFx.flags & 1))
3060 			ARX_SOUND_PlaySFX(SND_QUAKE, NULL, 1.0F - 0.5F * QuakeFx.intensity);
3061 
3062 		float truepower = periodicity * QuakeFx.intensity * itmod * 0.01f;
3063 		float halfpower = truepower * .5f;
3064 		ACTIVECAM->pos += randomVec(-halfpower, halfpower);
3065 		ACTIVECAM->angle.a += rnd() * truepower - halfpower;
3066 		ACTIVECAM->angle.g += rnd() * truepower - halfpower;
3067 		ACTIVECAM->angle.b += rnd() * truepower - halfpower;
3068 	}
3069 }
3070 
DANAE_StartNewQuest()3071 void DANAE_StartNewQuest()
3072 {
3073 	player.Interface = INTER_LIFE_MANA | INTER_MINIBACK | INTER_MINIBOOK;
3074 	PROGRESS_BAR_TOTAL = 108;
3075 	OLD_PROGRESS_BAR_COUNT=PROGRESS_BAR_COUNT=0;
3076 	LoadLevelScreen(1);
3077 	char loadfrom[256];
3078 	sprintf(loadfrom, "graph/levels/level1/level1.dlf");
3079 	DONT_ERASE_PLAYER=1;
3080 	DanaeClearAll();
3081 	PROGRESS_BAR_COUNT+=2.f;
3082 	LoadLevelScreen();
3083 	DanaeLoadLevel(loadfrom);
3084 	FirstFrame=1;
3085 	START_NEW_QUEST=0;
3086 	STARTED_A_GAME=1;
3087 	BLOCK_PLAYER_CONTROLS = 0;
3088 	FADEDURATION=0;
3089 	FADEDIR=0;
3090 	player.Interface = INTER_LIFE_MANA | INTER_MINIBACK | INTER_MINIBOOK;
3091 }
3092 
DANAE_ManageSplashThings()3093 bool DANAE_ManageSplashThings() {
3094 
3095 	const int SPLASH_DURATION = 3600;
3096 
3097 	GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapClamp);
3098 
3099 	if(SPLASH_THINGS_STAGE > 10) {
3100 
3101 		if(GInput->isAnyKeyPressed()) {
3102 			REFUSE_GAME_RETURN = 1;
3103 			FirstFrame=  1;
3104 			SPLASH_THINGS_STAGE = 0;
3105 			ARXmenu.currentmode = AMCM_MAIN;
3106 			ARX_MENU_Launch();
3107 		}
3108 
3109 		if(GInput->isKeyPressed(Keyboard::Key_Escape)) {
3110 			REFUSE_GAME_RETURN=1;
3111 			SPLASH_THINGS_STAGE = 14;
3112 		}
3113 
3114 		if (SPLASH_THINGS_STAGE==11)
3115 		{
3116 
3117 			if (SPLASH_START==0) //firsttime
3118 			{
3119 				if(!ARX_INTERFACE_InitFISHTANK())
3120 				{
3121 					SPLASH_THINGS_STAGE++;
3122 					return true;
3123 				}
3124 
3125 				SPLASH_START = arxtime.get_updated_ul();
3126 			}
3127 
3128 			ARX_INTERFACE_ShowFISHTANK();
3129 
3130 			unsigned long tim = arxtime.get_updated_ul();
3131 			float pos=(float)tim-(float)SPLASH_START;
3132 
3133 			if (pos>SPLASH_DURATION)
3134 			{
3135 				SPLASH_START=0;
3136 				SPLASH_THINGS_STAGE++;
3137 			}
3138 
3139 			GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapRepeat);
3140 			return true;
3141 
3142 		}
3143 
3144 		if (SPLASH_THINGS_STAGE==12)
3145 		{
3146 			if (SPLASH_START==0) //firsttime
3147 			{
3148 				if(!ARX_INTERFACE_InitARKANE())
3149 				{
3150 					SPLASH_THINGS_STAGE++;
3151 					return true;
3152 				}
3153 
3154 				SPLASH_START = arxtime.get_updated_ul();
3155 				ARX_SOUND_PlayInterface(SND_PLAYER_HEART_BEAT);
3156 			}
3157 
3158 			ARX_INTERFACE_ShowARKANE();
3159 			unsigned long tim = arxtime.get_updated_ul();
3160 			float pos=(float)tim-(float)SPLASH_START;
3161 
3162 			if (pos>SPLASH_DURATION)
3163 			{
3164 				SPLASH_START=0;
3165 				SPLASH_THINGS_STAGE++;
3166 			}
3167 
3168 			GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapRepeat);
3169 			return true;
3170 		}
3171 
3172 		if (SPLASH_THINGS_STAGE==13)
3173 		{
3174 			ARX_INTERFACE_KillFISHTANK();
3175 			ARX_INTERFACE_KillARKANE();
3176 			char loadfrom[256];
3177 
3178 			REFUSE_GAME_RETURN=1;
3179 			sprintf(loadfrom,"graph/levels/level10/level10.dlf");
3180 			OLD_PROGRESS_BAR_COUNT=PROGRESS_BAR_COUNT=0;
3181 			PROGRESS_BAR_TOTAL = 108;
3182 			LoadLevelScreen(10);
3183 
3184 			DanaeLoadLevel(loadfrom);
3185 			FirstFrame=1;
3186 			SPLASH_THINGS_STAGE=0;
3187 
3188 			GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapRepeat);
3189 			return true;
3190 
3191 		}
3192 
3193 		if (SPLASH_THINGS_STAGE > 13)
3194 		{
3195 			FirstFrame=1;
3196 			SPLASH_THINGS_STAGE=0;
3197 
3198 			GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapRepeat);
3199 			return true;
3200 		}
3201 	}
3202 
3203 	GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapRepeat);
3204 	return false;
3205 }
3206 
LaunchWaitingCine()3207 void LaunchWaitingCine() {
3208 
3209 	LogDebug("LaunchWaitingCine " << CINE_PRELOAD);
3210 
3211 	if(ACTIVECAM) {
3212 		ePos = ACTIVECAM->pos;
3213 	}
3214 
3215 	DANAE_KillCinematic();
3216 
3217 	res::path cinematic = res::path("graph/interface/illustrations") / WILL_LAUNCH_CINE;
3218 
3219 	if(resources->getFile(cinematic)) {
3220 
3221 		ControlCinematique->OneTimeSceneReInit();
3222 
3223 		if(loadCinematic(ControlCinematique, cinematic)) {
3224 
3225 			if(CINE_PRELOAD) {
3226 				LogDebug("only preloaded cinematic");
3227 				PLAY_LOADED_CINEMATIC = 0;
3228 			} else {
3229 				LogDebug("starting cinematic");
3230 				PLAY_LOADED_CINEMATIC = 1;
3231 				arxtime.pause();
3232 			}
3233 
3234 			LAST_LAUNCHED_CINE = WILL_LAUNCH_CINE;
3235 		} else {
3236 			LogWarning << "Error loading cinematic " << cinematic;
3237 		}
3238 
3239 	} else {
3240 		LogWarning << "Could not find cinematic " << cinematic;
3241 	}
3242 
3243 	WILL_LAUNCH_CINE.clear();
3244 }
3245 
3246 // Manages Currently playing 2D cinematic
DANAE_Manage_Cinematic()3247 long DANAE_Manage_Cinematic() {
3248 
3249 	float FrameTicks = arxtime.get_updated(false);
3250 
3251 	if(PLAY_LOADED_CINEMATIC == 1) {
3252 		LogDebug("really starting cinematic now");
3253 		LastFrameTicks = FrameTicks;
3254 		PLAY_LOADED_CINEMATIC=2;
3255 	}
3256 
3257 	PlayTrack(ControlCinematique);
3258 	ControlCinematique->InitDeviceObjects();
3259 	GRenderer->SetRenderState(Renderer::AlphaBlending, true);
3260 
3261 	ControlCinematique->Render(FrameTicks - LastFrameTicks);
3262 
3263 	//fin de l'anim
3264 	if ((!ControlCinematique->key)
3265 		|| (GInput->isKeyPressedNowUnPressed(Keyboard::Key_Escape))
3266 		|| (GInput->isKeyPressedNowUnPressed(Keyboard::Key_Escape)))
3267 	{
3268 		ControlCinematique->projectload=false;
3269 		StopSoundKeyFramer();
3270 		ControlCinematique->OneTimeSceneReInit();
3271 		ControlCinematique->DeleteDeviceObjects();
3272 		arxtime.resume();
3273 		PLAY_LOADED_CINEMATIC=0;
3274 
3275 		bool bWasBlocked = false;
3276 		if(BLOCK_PLAYER_CONTROLS) {
3277 			bWasBlocked = true;
3278 		}
3279 
3280 		// !! avant le cine end
3281 		if(ACTIVECAM) {
3282 			ACTIVECAM->pos = ePos;
3283 		}
3284 
3285 		if(bWasBlocked) {
3286 			BLOCK_PLAYER_CONTROLS =1;
3287 		}
3288 
3289 		ARX_SPEECH_Reset();
3290 		SendMsgToAllIO(SM_CINE_END, LAST_LAUNCHED_CINE);
3291 	}
3292 
3293 	LastFrameTicks = FrameTicks;
3294 	return 0;
3295 }
3296 
ReMappDanaeButton()3297 void ReMappDanaeButton() {
3298 
3299 	// Handle double clicks.
3300 	const ActionKey & button = config.actions[CONTROLS_CUST_ACTION].key[0];
3301 	if((button.key[0] != -1 && (button.key[0] & Mouse::ButtonBase)
3302 	    && GInput->getMouseButtonDoubleClick(button.key[0], 300))
3303 	   || (button.key[1] != -1 && (button.key[1] & Mouse::ButtonBase)
3304 	    && GInput->getMouseButtonDoubleClick(button.key[1], 300))) {
3305 		EERIEMouseButton |= 4;
3306 		EERIEMouseButton &= ~1;
3307 	}
3308 
3309 	if(GInput->actionNowPressed(CONTROLS_CUST_ACTION)) {
3310 		if(EERIEMouseButton & 4) {
3311 			EERIEMouseButton &= ~1;
3312 		} else {
3313 			EERIEMouseButton |= 1;
3314 		}
3315 
3316 	}
3317 	if(GInput->actionNowReleased(CONTROLS_CUST_ACTION)) {
3318 		EERIEMouseButton &= ~1;
3319 		EERIEMouseButton &= ~4;
3320 	}
3321 
3322 	if(GInput->actionNowPressed(CONTROLS_CUST_MOUSELOOK)) {
3323 		EERIEMouseButton |= 2;
3324 	}
3325 	if(GInput->actionNowReleased(CONTROLS_CUST_MOUSELOOK)) {
3326 		EERIEMouseButton &= ~2;
3327 	}
3328 
3329 }
3330 
AdjustMousePosition()3331 void AdjustMousePosition()
3332 {
3333 	if (EERIEMouseGrab && GInput->hasMouseMoved())
3334 	{
3335 		Vec2s pos;
3336 		pos.x = (short)(DANAESIZX >> 1);
3337 		pos.y = (short)(DANAESIZY >> 1);
3338 
3339 		if (!((ARXmenu.currentmode == AMCM_NEWQUEST)
3340 				||	(player.Interface & INTER_MAP && (Book_Mode != BOOKMODE_MINIMAP)))) {
3341 			GInput->setMousePosAbs(pos);
3342 		}
3343 	}
3344 }
3345 
ShowTestText()3346 void ShowTestText()
3347 {
3348 	char tex[256];
3349 
3350 	mainApp->OutputText(0, 16, arx_version);
3351 
3352 	sprintf(tex,"Level : %s", LastLoadedScene.string().c_str());
3353 	mainApp->OutputText( 0, 32, tex );
3354 
3355 	sprintf(tex,"Position : %5.0f %5.0f %5.0f",player.pos.x,player.pos.y,player.pos.z);
3356 	mainApp->OutputText( 0, 48, tex );
3357 
3358 	sprintf( tex,"Last Failed Sequence : %s",LAST_FAILED_SEQUENCE.c_str() );
3359 	mainApp->OutputText( 0, 64, tex );
3360 }
3361 
3362 extern float CURRENT_PLAYER_COLOR;
3363 
3364 long TSU_TEST_NB = 0;
3365 long TSU_TEST_NB_LIGHT = 0;
3366 
ShowInfoText()3367 void ShowInfoText() {
3368 
3369 	unsigned long uGAT = (unsigned long)(arxtime) / 1000;
3370 	long GAT=(long)uGAT;
3371 	char tex[256];
3372 	float fpss2=1000.f/framedelay;
3373 	LASTfpscount++;
3374 
3375 	float fps2v = std::max(fpss2, LASTfps2);
3376 	float fps2vmin = std::min(fpss2, LASTfps2);
3377 
3378 	if(LASTfpscount > 49)  {
3379 		LASTfps2 = 0;
3380 		LASTfpscount = 0;
3381 		fps2 = fps2v;
3382 		fps2min = fps2vmin;
3383 	} else {
3384 		LASTfps2 = fpss2;
3385 	}
3386 
3387 	sprintf(tex, "%ld Prims %4.02f fps ( %3.02f - %3.02f ) [%3.0fms] INTER:%ld [%3.06f", EERIEDrawnPolys, FPS, fps2min, fps2, framedelay, INTER_DRAW, vdist);
3388 	mainApp->OutputText( 70, 32, tex );
3389 
3390 	float poss=-666.66f;
3391 	EERIEPOLY * ep=CheckInPolyPrecis(player.pos.x,player.pos.y,player.pos.z);
3392 	float tempo=0.f;
3393 
3394 	if ((ep) && (GetTruePolyY(ep,&player.pos,&tempo)))
3395 		poss=tempo;
3396 
3397 	sprintf(tex,"Position  x:%7.0f y:%7.0f [%7.0f] z:%6.0f a%3.0f b%3.0f FOK %3.0f",player.pos.x,player.pos.y+player.size.y,poss,player.pos.z,player.angle.a,player.angle.b,ACTIVECAM->focal);
3398 	mainApp->OutputText( 70, 48, tex );
3399 	sprintf(tex,"AnchorPos x:%6.0f y:%6.0f z:%6.0f TIME %lds Part %ld - %d",player.pos.x-Mscenepos.x,player.pos.y+player.size.y-Mscenepos.y,player.pos.z-Mscenepos.z
3400 		,GAT, getParticleCount(),player.doingmagic);
3401 	mainApp->OutputText( 70, 64, tex );
3402 
3403 	if (player.onfirmground==0) mainApp->OutputText( 200, 280, "OFFGRND" );
3404 
3405 	sprintf(tex,"Jump %f cinema %f %d %d - Pathfind %ld(%s)",player.jumplastposition,CINEMA_DECAL,DANAEMouse.x,DANAEMouse.y,EERIE_PATHFINDER_Get_Queued_Number(), PATHFINDER_WORKING ? "Working" : "Idled");
3406 	mainApp->OutputText( 70, 80, tex );
3407 	Entity * io=ARX_SCRIPT_Get_IO_Max_Events();
3408 
3409 	if (io==NULL)
3410 		sprintf(tex,"Events %ld (IOmax N/A) Timers %ld",ScriptEvent::totalCount,ARX_SCRIPT_CountTimers());
3411 	else
3412 	{
3413 		sprintf(tex,"Events %ld (IOmax %s %d) Timers %ld",ScriptEvent::totalCount, io->long_name().c_str(), io->stat_count,ARX_SCRIPT_CountTimers());
3414 	}
3415 
3416 	mainApp->OutputText( 70, 94, tex );
3417 
3418 	io=ARX_SCRIPT_Get_IO_Max_Events_Sent();
3419 
3420 	if(io) {
3421 		sprintf(tex,"Max SENDER %s %d)", io->long_name().c_str(), io->stat_sent);
3422 		mainApp->OutputText(70, 114, tex);
3423 	}
3424 
3425 	float slope=0.f;
3426 	ep=CheckInPoly(player.pos.x,player.pos.y-10.f,player.pos.z);
3427 
3428 	if (ep)
3429 	{
3430 		slope=ep->norm.y;
3431 	}
3432 
3433 	sprintf(tex,"Velocity %3.0f %3.0f %3.0f Slope %3.3f",player.physics.velocity.x,player.physics.velocity.y,player.physics.velocity.z,slope);
3434 	mainApp->OutputText( 70, 128, tex );
3435 
3436 	sprintf(tex, "nblights %ld - nb %ld", TSU_TEST_NB_LIGHT, TSU_TEST_NB);
3437 	mainApp->OutputText( 100, 208, tex );
3438 	TSU_TEST_NB = 0;
3439 	TSU_TEST_NB_LIGHT = 0;
3440 
3441 #ifdef BUILD_EDITOR
3442 	if ((!EDITMODE) && (ValidIONum(LastSelectedIONum)))
3443 	{
3444 		io = entities[LastSelectedIONum];
3445 
3446 	  if (io)
3447 	  {
3448 		  if (io==entities.player())
3449 		  {
3450 			  	sprintf(tex,"%4.0f %4.0f %4.0f - %4.0f %4.0f %4.0f -- %3.0f %d/%ld targ %ld beh %ld",io->pos.x,
3451 					io->pos.y,io->pos.z,io->move.x,
3452 					io->move.y,io->move.z,io->_npcdata->moveproblem,io->_npcdata->pathfind.listpos,io->_npcdata->pathfind.listnb,
3453 					io->_npcdata->pathfind.truetarget, (long)io->_npcdata->behavior);
3454 				mainApp->OutputText(170, 420, tex);
3455 			sprintf(tex,"Life %4.0f/%4.0f Mana %4.0f/%4.0f Poisoned %3.1f Hunger %4.1f",player.life,player.maxlife,
3456 					player.mana,player.maxmana,player.poison,player.hunger);
3457 				mainApp->OutputText( 170, 320, tex );
3458 
3459 		  }
3460 		  else
3461 		  {
3462 			  if (io->ioflags & IO_NPC)
3463 			  {
3464 
3465 				sprintf(tex,"%4.0f %4.0f %4.0f - %4.0f %4.0f %4.0f -- %3.0f %d/%ld targ %ld beh %ld",io->pos.x,
3466 					io->pos.y,io->pos.z,io->move.x,
3467 					io->move.y,io->move.z,io->_npcdata->moveproblem,io->_npcdata->pathfind.listpos,io->_npcdata->pathfind.listnb,
3468 					io->_npcdata->pathfind.truetarget, (long)io->_npcdata->behavior);
3469 				mainApp->OutputText(170, 420, tex);
3470 				sprintf(tex,"Life %4.0f/%4.0f Mana %4.0f/%4.0f Poisoned %3.1f",io->_npcdata->life,io->_npcdata->maxlife,
3471 					io->_npcdata->mana,io->_npcdata->maxmana,io->_npcdata->poisonned);
3472 				mainApp->OutputText( 170, 320, tex );
3473 				sprintf(tex,"AC %3.0f Absorb %3.0f",ARX_INTERACTIVE_GetArmorClass(io),io->_npcdata->absorb);
3474 				mainApp->OutputText( 170, 335, tex );
3475 
3476 				if (io->_npcdata->pathfind.flags  & PATHFIND_ALWAYS)
3477 					mainApp->OutputText( 170, 360, "PF_ALWAYS" );
3478 				else
3479 				{
3480 					sprintf(tex, "PF_%ld", (long)io->_npcdata->pathfind.flags);
3481 					mainApp->OutputText(170, 360, tex);
3482 				}
3483 			  }
3484 
3485 			  if (io->ioflags & IO_FIX)
3486 			  {
3487 				sprintf(tex,"Durability %4.0f/%4.0f Poisonous %3d count %d",io->durability,io->max_durability,io->poisonous,io->poisonous_count);
3488 				mainApp->OutputText( 170, 320, tex );
3489 			  }
3490 
3491 			  if (io->ioflags & IO_ITEM)
3492 			  {
3493 				sprintf(tex,"Durability %4.0f/%4.0f Poisonous %3d count %d",io->durability,io->max_durability,io->poisonous,io->poisonous_count);
3494 				mainApp->OutputText( 170, 320, tex );
3495 			  }
3496 		  }
3497 	  }
3498 	}
3499 #endif // BUILD_EDITOR
3500 
3501 	long zap=IsAnyPolyThere(player.pos.x,player.pos.z);
3502 	sprintf(tex,"POLY %ld",zap);
3503 	mainApp->OutputText( 270, 220, tex );
3504 
3505 	sprintf(tex,"COLOR %3.0f Stealth %3.0f",CURRENT_PLAYER_COLOR,GetPlayerStealth());
3506 	mainApp->OutputText( 270, 200, tex );
3507 
3508 	ARX_SCRIPT_Init_Event_Stats();
3509 }
3510 
ShowFPS()3511 void ShowFPS() {
3512 	// TODO: make sure when adding text that it can fit here
3513 	// - this is extremely naughty, should use a std::string
3514 	char tex[32];
3515 	sprintf(tex, "%.02f fps", (float)FPS);
3516 
3517 	// top left
3518 	mainApp->OutputTextGrid(0.0f, 0.0f, tex);
3519 
3520 	// bottom right
3521 	//mainApp->OutputTextGrid(-0.5f, -1, tex);
3522 }
3523 
ARX_SetAntiAliasing()3524 void ARX_SetAntiAliasing() {
3525 	GRenderer->SetAntialiasing(config.video.antialiasing);
3526 }
3527 
ReleaseSystemObjects()3528 void ReleaseSystemObjects() {
3529 
3530 	delete hero, hero = NULL;
3531 
3532 	if(entities.size() > 0 && entities.player() != NULL) {
3533 		entities.player()->obj = NULL; // already deleted above (hero)
3534 		delete entities.player();
3535 		arx_assert(entities.size() > 0 && entities.player() == NULL);
3536 	}
3537 
3538 	delete eyeballobj, eyeballobj = NULL;
3539 	delete cabal, cabal = NULL;
3540 	delete nodeobj, nodeobj = NULL;
3541 	delete fogobj, fogobj = NULL;
3542 	delete cameraobj, cameraobj = NULL;
3543 	delete markerobj, markerobj = NULL;
3544 	delete arrowobj, arrowobj = NULL;
3545 
3546 	BOOST_FOREACH(EERIE_3DOBJ * & obj, GoldCoinsObj) {
3547 		delete obj, obj = NULL;
3548 	}
3549 }
3550 
shutdownGame()3551 void shutdownGame() {
3552 
3553 	ARX_Menu_Resources_Release();
3554 	arxtime.resume();
3555 
3556 	mainApp->GetWindow()->hide();
3557 
3558 	g_miniMap.purgeTexContainer();
3559 
3560 	KillInterfaceTextureContainers();
3561 	Menu2_Close();
3562 	DanaeClearLevel(2);
3563 	TextureContainer::DeleteAll();
3564 
3565 	delete ControlCinematique, ControlCinematique = NULL;
3566 
3567 	config.save();
3568 
3569 	RoomDrawRelease();
3570 	EXITING=1;
3571 	TREATZONE_Release();
3572 	ClearTileLights();
3573 
3574 	// texts and textures
3575 	ClearSysTextures();
3576 
3577 	delete pParticleManager, pParticleManager = NULL;
3578 
3579 	//sound
3580 	ARX_SOUND_Release();
3581 	MCache_ClearAll();
3582 
3583 	//pathfinding
3584 	ARX_PATH_ReleaseAllPath();
3585 	ReleaseSystemObjects();
3586 
3587 	//background
3588 	ClearBackground(ACTIVEBKG);
3589 
3590 	//animations
3591 	EERIE_ANIMMANAGER_ClearAll();
3592 
3593 	//Scripts
3594 	if(svar) {
3595 		for(long i = 0; i < NB_GLOBALS; i++) {
3596 			free(svar[i].text), svar[i].text = NULL;
3597 		}
3598 		free(svar), svar = NULL;
3599 	}
3600 
3601 	ARX_SCRIPT_Timer_ClearAll();
3602 
3603 	delete[] scr_timer, scr_timer = NULL;
3604 
3605 	//Speech
3606 	ARX_SPEECH_ClearAll();
3607 	ARX_Text_Close();
3608 
3609 	//object loaders from beforerun
3610 	ReleaseDanaeBeforeRun();
3611 
3612 	delete resources;
3613 
3614 	ReleaseNode();
3615 
3616 	// Current game
3617 	ARX_Changelevel_CurGame_Clear();
3618 
3619 	//Halo
3620 	ReleaseHalo();
3621 	FreeSnapShot();
3622 	ARX_INPUT_Release();
3623 
3624 	mainApp->Cleanup3DEnvironment();
3625 
3626 
3627 	LogInfo << "Clean shutdown";
3628 }
3629