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-2000 ARKANE Studios SA. All rights reserved
46
47 #include "game/Player.h"
48
49 #include <stddef.h>
50 #include <cstdlib>
51 #include <cstring>
52 #include <algorithm>
53 #include <limits>
54
55 #include "ai/PathFinderManager.h"
56 #include "ai/Paths.h"
57
58 #include "core/Application.h"
59 #include "core/Localisation.h"
60 #include "core/GameTime.h"
61 #include "core/Core.h"
62
63 #include "game/Damage.h"
64 #include "game/EntityManager.h"
65 #include "game/Equipment.h"
66 #include "game/Inventory.h"
67 #include "game/Item.h"
68 #include "game/Missile.h"
69 #include "game/NPC.h"
70
71 #include "gui/Menu.h"
72 #include "gui/Text.h"
73 #include "gui/Speech.h"
74 #include "gui/Interface.h"
75 #include "gui/MiniMap.h"
76
77 #include "graphics/BaseGraphicsTypes.h"
78 #include "graphics/Color.h"
79 #include "graphics/Draw.h"
80 #include "graphics/GraphicsModes.h"
81 #include "graphics/GraphicsTypes.h"
82 #include "graphics/Math.h"
83 #include "graphics/Renderer.h"
84 #include "graphics/Vertex.h"
85 #include "graphics/data/TextureContainer.h"
86 #include "graphics/effects/Fog.h"
87 #include "graphics/particle/ParticleManager.h"
88 #include "graphics/particle/ParticleEffects.h"
89
90 #include "io/resource/ResourcePath.h"
91 #include "io/resource/PakReader.h"
92 #include "io/fs/Filesystem.h"
93 #include "io/log/Logger.h"
94
95 #include "math/Angle.h"
96 #include "math/Random.h"
97 #include "math/Vector3.h"
98
99 #include "physics/Collisions.h"
100 #include "physics/Attractors.h"
101
102 #include "platform/Platform.h"
103
104 #include "scene/ChangeLevel.h"
105 #include "scene/Scene.h"
106 #include "scene/GameSound.h"
107 #include "scene/Interactive.h"
108 #include "scene/Light.h"
109 #include "scene/Object.h"
110
111 #include "script/Script.h"
112
113 using std::vector;
114
115 extern long ARX_CONVERSATION;
116 extern long HERO_SHOW_1ST;
117 extern long REQUEST_SPEECH_SKIP;
118 extern long CHANGE_LEVEL_ICON;
119 extern long DONT_ERASE_PLAYER;
120 extern long GLOBAL_MAGIC_MODE;
121 extern QUAKE_FX_STRUCT QuakeFx;
122 extern Entity * CURRENT_TORCH;
123 extern Entity * CAMERACONTROLLER;
124 extern ParticleManager * pParticleManager;
125
126 extern unsigned long LAST_JUMP_ENDTIME;
127
128 static const float WORLD_GRAVITY = 0.1f;
129 static const float JUMP_GRAVITY = 0.02f;
130 static const float STEP_DISTANCE = 120.f;
131 static const float TARGET_DT = 1000.f / 30.f;
132
133 extern Vec3f PUSH_PLAYER_FORCE;
134 extern bool bBookHalo;
135 extern bool bGoldHalo;
136 extern float InventoryX;
137 extern float InventoryDir;
138 extern long COLLIDED_CLIMB_POLY;
139 extern long HERO_SHOW_1ST;
140 extern long STARTED_A_GAME;
141 extern bool TRUE_PLAYER_MOUSELOOK_ON;
142 extern unsigned long ulBookHaloTime;
143 extern unsigned long ulGoldHaloTime;
144 extern long cur_rf;
145
146 static const float ARX_PLAYER_SKILL_STEALTH_MAX = 100.f;
147
148 ARXCHARACTER player;
149 EERIE_3DOBJ * hero = NULL;
150 float currentdistance = 0.f;
151 float CURRENT_PLAYER_COLOR = 0;
152 float DeadCameraDistance = 0.f;
153 float PLAYER_ROTATION = 0;
154
155 long USE_PLAYERCOLLISIONS = 1;
156 long BLOCK_PLAYER_CONTROLS = 0;
157 long WILLRETURNTOCOMBATMODE = 0;
158 long DeadTime = 0;
159 static unsigned long LastHungerSample = 0;
160 static unsigned long ROTATE_START = 0;
161 long sp_max = 0;
162
163 // Player Anims FLAGS/Vars
164 ANIM_HANDLE * herowaitbook = NULL;
165 ANIM_HANDLE * herowait_2h = NULL;
166
167 ARX_NECKLACE necklace;
168
169 vector<KEYRING_SLOT> Keyring;
170 Entity * CURRENT_TORCH = NULL;
171
172 static unsigned long FALLING_TIME = 0;
173
174 vector<STRUCT_QUEST> PlayerQuest;
175 long FistParticles = 0;
176 void Manage_sp_max();
ARX_PLAYER_IsInFightMode()177 bool ARX_PLAYER_IsInFightMode() {
178 if (player.Interface & INTER_COMBATMODE) return true;
179
180 if(entities.size() > 0 && entities.player()
181 && entities.player()->animlayer[1].cur_anim) {
182
183 ANIM_USE * ause1 = &entities.player()->animlayer[1];
184 ANIM_HANDLE ** alist = entities.player()->anims;
185
186 if ((ause1->cur_anim == alist[ANIM_BARE_READY])
187 || (ause1->cur_anim == alist[ANIM_BARE_UNREADY])
188 || (ause1->cur_anim == alist[ANIM_DAGGER_READY_PART_1])
189 || (ause1->cur_anim == alist[ANIM_DAGGER_READY_PART_2])
190 || (ause1->cur_anim == alist[ANIM_DAGGER_UNREADY_PART_1])
191 || (ause1->cur_anim == alist[ANIM_DAGGER_UNREADY_PART_2])
192 || (ause1->cur_anim == alist[ANIM_1H_READY_PART_1])
193 || (ause1->cur_anim == alist[ANIM_1H_READY_PART_2])
194 || (ause1->cur_anim == alist[ANIM_1H_UNREADY_PART_1])
195 || (ause1->cur_anim == alist[ANIM_1H_UNREADY_PART_2])
196 || (ause1->cur_anim == alist[ANIM_2H_READY_PART_1])
197 || (ause1->cur_anim == alist[ANIM_2H_READY_PART_2])
198 || (ause1->cur_anim == alist[ANIM_2H_UNREADY_PART_1])
199 || (ause1->cur_anim == alist[ANIM_2H_UNREADY_PART_2])
200 || (ause1->cur_anim == alist[ANIM_MISSILE_READY_PART_1])
201 || (ause1->cur_anim == alist[ANIM_MISSILE_READY_PART_2])
202 || (ause1->cur_anim == alist[ANIM_MISSILE_UNREADY_PART_1])
203 || (ause1->cur_anim == alist[ANIM_MISSILE_UNREADY_PART_2])
204 )
205 return true;
206 }
207
208 return false;
209 }
210 //*************************************************************************************
211 //*************************************************************************************
212 // KEYRING FUNCTIONS
213 //-------------------------------------------------------------------------------------
214
215 //*************************************************************************************
216 // void ARX_KEYRING_Init()
217 //-------------------------------------------------------------------------------------
218 // FUNCTION/RESULT:
219 // Init/Reset player Keyring structures
220 //*************************************************************************************
ARX_KEYRING_Init()221 void ARX_KEYRING_Init() {
222 Keyring.clear();
223 }
224 //*************************************************************************************
225 // void ARX_KEYRING_Add(char * key)
226 //-------------------------------------------------------------------------------------
227 // FUNCTION/RESULT:
228 // Add a key to Keyring
229 //*************************************************************************************
ARX_KEYRING_Add(const std::string & key)230 void ARX_KEYRING_Add(const std::string & key) {
231 Keyring.resize(Keyring.size() + 1);
232 memset(&Keyring.back(), 0, sizeof(KEYRING_SLOT));
233 strcpy(Keyring.back().slot, key.c_str());
234 }
235
236 //*************************************************************************************
237 // void ARX_KEYRING_Combine(Entity * io)
238 //-------------------------------------------------------------------------------------
239 // FUNCTION/RESULT:
240 // Sends COMBINE event to "io" for each keyring entry
241 //*************************************************************************************
ARX_KEYRING_Combine(Entity * io)242 void ARX_KEYRING_Combine(Entity * io) {
243 for(size_t i = 0; i < Keyring.size(); i++) {
244 if(SendIOScriptEvent(io, SM_COMBINE, Keyring[i].slot) == REFUSE) {
245 return;
246 }
247 }
248 }
249 //-----------------------------------------------------------------------------
250 // KEYRING FUNCTIONS end
251 //******************************************************************************
252
253 //-----------------------------------------------------------------------------
254 //*************************************************************************************
255 // void ARX_PLAYER_FrontPos(EERIE_3D * pos)
256 //-------------------------------------------------------------------------------------
257 // FUNCTION/RESULT:
258 // Fills "pos" with player "front pos" for sound purpose
259 //*************************************************************************************
ARX_PLAYER_FrontPos(Vec3f * pos)260 void ARX_PLAYER_FrontPos(Vec3f * pos)
261 {
262 pos->x = player.pos.x - EEsin(radians(MAKEANGLE(player.angle.b))) * 100.f;
263 pos->y = player.pos.y + 100.f; //-100.f;
264 pos->z = player.pos.z + EEcos(radians(MAKEANGLE(player.angle.b))) * 100.f;
265 }
266
267 // FUNCTION/RESULT:
268 // Reset all extra-rotation groups of player
ARX_PLAYER_RectifyPosition()269 void ARX_PLAYER_RectifyPosition() {
270 Entity * io = entities.player();
271 if(io && io->_npcdata->ex_rotate) {
272 for(long n = 0; n < MAX_EXTRA_ROTATE; n++) {
273 io->_npcdata->ex_rotate->group_rotate[n] = Anglef::ZERO;
274 }
275 io->_npcdata->ex_rotate->flags = 0;
276 }
277 }
278
279 //******************************************************************************
280 // PLAYER TORCH FUNCTIONS
281 //-----------------------------------------------------------------------------
ARX_PLAYER_KillTorch()282 void ARX_PLAYER_KillTorch() {
283
284 ARX_SOUND_PlaySFX(SND_TORCH_END);
285 ARX_SOUND_Stop(SND_TORCH_LOOP);
286
287 giveToPlayer(CURRENT_TORCH);
288
289 CURRENT_TORCH = NULL;
290 SHOW_TORCH = 0;
291 DynLight[0].exist = 0;
292 }
293
294 //-----------------------------------------------------------------------------
ARX_PLAYER_ClickedOnTorch(Entity * io)295 void ARX_PLAYER_ClickedOnTorch(Entity * io)
296 {
297 if (io == NULL)
298 {
299 return;
300 }
301
302 if (CURRENT_TORCH == NULL)
303 {
304 if (io->durability > 0)
305 {
306 if (io->ignition > 0)
307 {
308 if (ValidDynLight(io->ignit_light))
309 DynLight[io->ignit_light].exist = 0;
310
311 io->ignit_light = -1;
312
313 if (io->ignit_sound != audio::INVALID_ID)
314 {
315 ARX_SOUND_Stop(io->ignit_sound);
316 io->ignit_sound = audio::INVALID_ID;
317 }
318
319 io->ignition = 0;
320 }
321
322 SHOW_TORCH = 1;
323 ARX_SOUND_PlaySFX(SND_TORCH_START);
324 ARX_SOUND_PlaySFX(SND_TORCH_LOOP, NULL, 1.0F, ARX_SOUND_PLAY_LOOPED);
325 RemoveFromAllInventories(io);
326 CURRENT_TORCH = io;
327 io->show = SHOW_FLAG_ON_PLAYER;
328
329 if (DRAGINTER == io)
330 {
331 DRAGINTER = NULL;
332 }
333 }
334 }
335 else if (CURRENT_TORCH == io)
336 {
337 ARX_PLAYER_KillTorch();
338
339 }
340 else
341 {
342 ARX_PLAYER_KillTorch();
343
344 if (io->durability > 0)
345 {
346 if (io->ignition > 0)
347 {
348 if (io->ignit_light != -1)
349 {
350 DynLight[io->ignit_light].exist = 0;
351 io->ignit_light = -1;
352 }
353
354 if (io->ignit_sound != audio::INVALID_ID)
355 {
356 ARX_SOUND_Stop(io->ignit_sound);
357 io->ignit_sound = audio::INVALID_ID;
358 }
359
360 io->ignition = 0;
361 }
362
363 SHOW_TORCH = 1;
364 ARX_SOUND_PlaySFX(SND_TORCH_START);
365 ARX_SOUND_PlaySFX(SND_TORCH_LOOP, NULL, 1.0F, ARX_SOUND_PLAY_LOOPED);
366 RemoveFromAllInventories(io);
367 CURRENT_TORCH = io;
368 io->show = SHOW_FLAG_ON_PLAYER;
369
370 if (DRAGINTER == io)
371 {
372 DRAGINTER = NULL;
373 }
374 }
375 }
376 }
377
ARX_PLAYER_ManageTorch()378 static void ARX_PLAYER_ManageTorch() {
379 if (CURRENT_TORCH)
380 {
381 CURRENT_TORCH->ignition = 0;
382 CURRENT_TORCH->durability -= FrameDiff * ( 1.0f / 10000 );
383
384 if (CURRENT_TORCH->durability <= 0)
385 {
386
387 ARX_SPEECH_ReleaseIOSpeech(CURRENT_TORCH);
388 // Need To Kill timers
389 ARX_SCRIPT_Timer_Clear_By_IO(CURRENT_TORCH);
390 CURRENT_TORCH->show = SHOW_FLAG_KILLED;
391 CURRENT_TORCH->gameFlags &= ~GFLAG_ISINTREATZONE;
392 RemoveFromAllInventories(CURRENT_TORCH);
393 ARX_INTERACTIVE_DestroyDynamicInfo(CURRENT_TORCH);
394 ARX_SOUND_PlaySFX(SND_TORCH_END);
395 ARX_SOUND_Stop(SND_TORCH_LOOP);
396 ARX_INTERACTIVE_DestroyIO(CURRENT_TORCH);
397 CURRENT_TORCH = NULL;
398 SHOW_TORCH = 0;
399 DynLight[0].exist = 0;
400 }
401 }
402 }
403 //-----------------------------------------------------------------------------
404 // PLAYER TORCH FUNCTIONS end
405 //******************************************************************************
406
407
408 //*************************************************************************************
409 // void ARX_PLAYER_Quest_Init()
410 //-------------------------------------------------------------------------------------
411 // FUNCTION/RESULT:
412 // Init/Reset player Quest structures
413 //*************************************************************************************
ARX_PLAYER_Quest_Init()414 void ARX_PLAYER_Quest_Init() {
415 PlayerQuest.clear();
416 gui::updateQuestBook();
417 }
418
419 //*************************************************************************************
420 // void ARX_Player_Rune_Add(unsigned long _ulRune)
421 //-------------------------------------------------------------------------------------
422 // FUNCTION/RESULT:
423 // Add _ulRune to player runes
424 //*************************************************************************************
ARX_Player_Rune_Add(RuneFlag _ulRune)425 void ARX_Player_Rune_Add(RuneFlag _ulRune)
426 {
427 int iNbSpells = 0;
428 int iNbSpellsAfter = 0;
429
430 for (size_t i = 0; i < SPELL_COUNT; i++)
431 {
432 if (spellicons[i].bSecret == false)
433 {
434 long j = 0;
435 bool bOk = true;
436
437 while ((j < 4) && (spellicons[i].symbols[j] != 255))
438 {
439 if (!(player.rune_flags & (RuneFlag)(1 << spellicons[i].symbols[j])))
440 {
441 bOk = false;
442 }
443
444 j++;
445 }
446
447 if (bOk)
448 {
449 iNbSpells ++;
450 }
451 }
452 }
453
454 player.rune_flags |= _ulRune;
455
456 for (size_t i = 0; i < SPELL_COUNT; i++)
457 {
458 if (spellicons[i].bSecret == false)
459 {
460 long j = 0;
461 bool bOk = true;
462
463 while ((j < 4) && (spellicons[i].symbols[j] != 255))
464 {
465 if (!(player.rune_flags & (RuneFlag)(1 << spellicons[i].symbols[j])))
466 {
467 bOk = false;
468 }
469
470 j++;
471 }
472
473 if (bOk)
474 {
475 iNbSpellsAfter ++;
476 }
477 }
478 }
479
480 if(iNbSpellsAfter > iNbSpells) {
481 MakeBookFX(Vec3f(DANAESIZX - INTERFACE_RATIO(35), DANAESIZY - INTERFACE_RATIO(148),
482 0.00001f));
483 bBookHalo = true;
484 ulBookHaloTime = 0;
485 }
486 }
487
488 //*************************************************************************************
489 // void ARX_Player_Rune_Remove(unsigned long _ulRune
490 //-------------------------------------------------------------------------------------
491 // FUNCTION/RESULT:
492 // Remove _ulRune from player runes
493 //*************************************************************************************
ARX_Player_Rune_Remove(RuneFlag _ulRune)494 void ARX_Player_Rune_Remove(RuneFlag _ulRune)
495 {
496 player.rune_flags &= ~_ulRune;
497 }
498
499 //*************************************************************************************
500 // void ARX_PLAYER_Quest_Add(char * quest)
501 //-------------------------------------------------------------------------------------
502 // FUNCTION/RESULT:
503 // Add quest "quest" to player Questbook
504 //*************************************************************************************
ARX_PLAYER_Quest_Add(const std::string & quest,bool _bLoad)505 void ARX_PLAYER_Quest_Add(const std::string & quest, bool _bLoad) {
506
507 PlayerQuest.push_back(STRUCT_QUEST());
508 PlayerQuest.back().ident = quest;
509 bBookHalo = !_bLoad;
510 ulBookHaloTime = 0;
511
512 gui::updateQuestBook();
513 }
514
515 //*************************************************************************************
516 // void ARX_PLAYER_Remove_Invisibility()
517 //-------------------------------------------------------------------------------------
518 // FUNCTION/RESULT:
519 // Removes player invisibility by killing Invisibility spells on him
520 //*************************************************************************************
ARX_PLAYER_Remove_Invisibility()521 void ARX_PLAYER_Remove_Invisibility() {
522 for(size_t i = 0; i < MAX_SPELLS; i++) {
523 if(spells[i].exist && spells[i].type == SPELL_INVISIBILITY && spells[i].caster == 0) {
524 spells[i].tolive = 0;
525 }
526 }
527 }
528
529 /* TODO use this table instead of the copied functions below!
530 static const size_t max_skills = 9;
531 static const size_t max_attributes = 4;
532 static const float skill_attribute_factors[max_skills][max_attributes] = {
533 // Str Men Dex Con
534 { 0.0f, 0.0f, 2.0f, 0.0f }, // Stealth
535 { 0.0f, 1.0f, 1.0f, 0.0f }, // Technical
536 { 0.0f, 2.0f, 0.0f, 0.0f }, // Intuition
537 { 0.0f, 2.0f, 0.0f, 0.0f }, // Ethereal link
538 { 0.5f, 1.5f, 0.5f, 0.0f }, // Object knowledge
539 { 0.0f, 2.0f, 0.0f, 0.0f }, // Casting
540 { 2.0f, 0.0f, 1.0f, 0.0f }, // Close combat
541 { 1.0f, 0.0f, 2.0f, 0.0f }, // Projectile
542 { 0.0f, 0.0f, 0.0f, 1.0f }, // Defense
543 };
544 */
545
546 //*************************************************************************************
547 // FUNCTION/RESULT:
548 // Returns player Stealth Skill level (Plain (type==0) or Modified (type==1))
549 //*************************************************************************************
ARX_PLAYER_Get_Skill_Stealth(long type)550 static float ARX_PLAYER_Get_Skill_Stealth(long type) {
551 if(type == 0) {
552 return player.Skill_Stealth + player.Attribute_Dexterity * 2.f;
553 } else {
554 return player.Skill_Stealth + player.Mod_Skill_Stealth
555 + player.Full_Attribute_Dexterity * 2.f;
556 }
557 }
558 //*************************************************************************************
559 // FUNCTION/RESULT:
560 // Returns player Mecanism Skill level (Plain (type==0) or Modified (type==1))
561 //*************************************************************************************
ARX_PLAYER_Get_Skill_Mecanism(long type)562 static float ARX_PLAYER_Get_Skill_Mecanism(long type) {
563 if(type == 0) {
564 return player.Skill_Mecanism + player.Attribute_Dexterity + player.Attribute_Mind;
565 } else {
566 return player.Skill_Mecanism + player.Mod_Skill_Mecanism
567 + player.Full_Attribute_Dexterity + player.Full_Attribute_Mind;
568 }
569 }
570 //*************************************************************************************
571 // FUNCTION/RESULT:
572 // Returns player Intuition Skill level (Plain (type==0) or Modified (type==1))
573 //*************************************************************************************
ARX_PLAYER_Get_Skill_Intuition(long type)574 static float ARX_PLAYER_Get_Skill_Intuition(long type) {
575 if(type == 0) {
576 return player.Skill_Intuition + player.Attribute_Mind * 2.f;
577 } else {
578 return player.Skill_Intuition + player.Mod_Skill_Intuition
579 + player.Full_Attribute_Mind * 2.f;
580 }
581 }
582 //*************************************************************************************
583 // FUNCTION/RESULT:
584 // Returns player Etheral Link Skill level (Plain (type==0) or Modified (type==1))
585 //*************************************************************************************
ARX_PLAYER_Get_Skill_Etheral_Link(long type)586 static float ARX_PLAYER_Get_Skill_Etheral_Link(long type) {
587 if(type == 0) {
588 return player.Skill_Etheral_Link + player.Attribute_Mind * 2.f;
589 } else {
590 return player.Skill_Etheral_Link + player.Mod_Skill_Etheral_Link
591 + player.Full_Attribute_Mind * 2.f;
592 }
593 }
594 //*************************************************************************************
595 // FUNCTION/RESULT:
596 // Returns player Object Knowledge Skill level (Plain (type==0) or Modified (type==1))
597 //*************************************************************************************
ARX_PLAYER_Get_Skill_Object_Knowledge(long type)598 static float ARX_PLAYER_Get_Skill_Object_Knowledge(long type) {
599 if(type == 0) {
600 return player.Skill_Object_Knowledge + player.Attribute_Mind * 1.5f
601 + player.Attribute_Dexterity * 0.5f + player.Attribute_Strength * 0.5f;
602 } else {
603 return player.Skill_Object_Knowledge + player.Mod_Skill_Object_Knowledge
604 + player.Full_Attribute_Mind * 1.5f + player.Full_Attribute_Dexterity * 0.5f
605 + player.Full_Attribute_Strength * 0.5f;
606 }
607 }
608 //*************************************************************************************
609 // FUNCTION/RESULT:
610 // Returns player Casting Skill level (Plain (type==0) or Modified (type==1))
611 //*************************************************************************************
ARX_PLAYER_Get_Skill_Casting(long type)612 static float ARX_PLAYER_Get_Skill_Casting(long type) {
613 if(type == 0) {
614 return player.Skill_Casting + player.Attribute_Mind * 2.f;
615 } else {
616 return player.Skill_Casting + player.Mod_Skill_Casting
617 + player.Full_Attribute_Mind * 2.f;
618 }
619 }
620 //*************************************************************************************
621 // FUNCTION/RESULT:
622 // Returns player Projectile Skill level (Plain (type==0) or Modified (type==1))
623 //*************************************************************************************
ARX_PLAYER_Get_Skill_Projectile(long type)624 static float ARX_PLAYER_Get_Skill_Projectile(long type) {
625 if(type == 0) {
626 return player.Skill_Projectile
627 + player.Attribute_Dexterity * 2.f + player.Attribute_Strength;
628 } else {
629 return player.Skill_Projectile + player.Mod_Skill_Projectile
630 + player.Full_Attribute_Dexterity * 2.f + player.Full_Attribute_Strength;
631 }
632 }
633 //*************************************************************************************
634 // FUNCTION/RESULT:
635 // Returns player Close Combat Skill level (Plain (type==0) or Modified (type==1))
636 //*************************************************************************************
ARX_PLAYER_Get_Skill_Close_Combat(long type)637 static float ARX_PLAYER_Get_Skill_Close_Combat(long type) {
638 if(type == 0) {
639 return player.Skill_Close_Combat
640 + player.Attribute_Dexterity + player.Attribute_Strength * 2.f;
641 } else {
642 return player.Skill_Close_Combat + player.Mod_Skill_Close_Combat
643 + player.Full_Attribute_Dexterity + player.Full_Attribute_Strength * 2.f;
644 }
645 }
646 //*************************************************************************************
647 // FUNCTION/RESULT:
648 // Returns player Defense Skill level (Plain (type==0) or Modified (type==1))
649 //*************************************************************************************
ARX_PLAYER_Get_Skill_Defense(long type)650 static float ARX_PLAYER_Get_Skill_Defense(long type) {
651 if(type == 0) {
652 return player.Skill_Defense + player.Attribute_Constitution * 3;
653 } else {
654 return player.Skill_Defense + player.Mod_Skill_Defense
655 + player.Full_Attribute_Constitution * 3;
656 }
657 }
658
659 //*************************************************************************************
660 // void ARX_PLAYER_ComputePlayerStats()
661 //-------------------------------------------------------------------------------------
662 // FUNCTION/RESULT:
663 // Compute secondary attributes for player
664 //*************************************************************************************
ARX_PLAYER_ComputePlayerStats()665 static void ARX_PLAYER_ComputePlayerStats() {
666
667 player.maxlife = (float)player.Attribute_Constitution * (float)(player.level + 2);
668 player.maxmana = (float)player.Attribute_Mind * (float)(player.level + 1);
669 float t = ARX_PLAYER_Get_Skill_Defense(0);
670
671
672 float fCalc = t * ( 1.0f / 10 ) - 1 ;
673 player.armor_class = checked_range_cast<unsigned char>(fCalc);
674
675
676 if (player.armor_class < 1) player.armor_class = 1;
677
678 player.resist_magic = (unsigned char)(float)(player.Attribute_Mind * 2.f
679 * (1.f + (ARX_PLAYER_Get_Skill_Casting(0)) * ( 1.0f / 200 )));
680
681 fCalc = player.Attribute_Constitution * 2 + ((ARX_PLAYER_Get_Skill_Defense(1) * ( 1.0f / 4 )));
682 player.resist_poison = checked_range_cast<unsigned char>(fCalc);
683
684
685 player.damages = (player.Attribute_Strength - 10) * ( 1.0f / 2 );
686
687 if (player.damages < 1.f) player.damages = 1.f;
688
689 player.AimTime = 1500;
690 }
691 extern long cur_mr;
692 extern long SPECIAL_PNUX;
693 //*************************************************************************************
694 // void ARX_PLAYER_ComputePlayerFullStats()
695 //-------------------------------------------------------------------------------------
696 // FUNCTION/RESULT:
697 // Compute FULL versions of player stats including Equiped Items
698 // and spells, and any other effect altering them.
699 //*************************************************************************************
ARX_PLAYER_ComputePlayerFullStats()700 void ARX_PLAYER_ComputePlayerFullStats()
701 {
702 ARX_PLAYER_ComputePlayerStats();
703 player.Mod_Attribute_Strength = 0;
704 player.Mod_Attribute_Dexterity = 0;
705 player.Mod_Attribute_Constitution = 0;
706 player.Mod_Attribute_Mind = 0;
707 player.Mod_Skill_Stealth = 0;
708 player.Mod_Skill_Mecanism = 0;
709 player.Mod_Skill_Intuition = 0;
710 player.Mod_Skill_Etheral_Link = 0;
711 player.Mod_Skill_Object_Knowledge = 0;
712 player.Mod_Skill_Casting = 0;
713 player.Mod_Skill_Projectile = 0;
714 player.Mod_Skill_Close_Combat = 0;
715 player.Mod_Skill_Defense = 0;
716 player.Mod_armor_class = 0;
717 player.Mod_resist_magic = 0;
718 player.Mod_resist_poison = 0;
719 player.Mod_Critical_Hit = 0;
720 player.Mod_damages = 0;
721
722 ARX_EQUIPMENT_IdentifyAll();
723
724 player.Full_Weapon_Type = ARX_EQUIPMENT_GetPlayerWeaponType();
725
726 Entity * io = entities.player();
727 // Check for Equipment Modificators to Attributes
728 player.Mod_Attribute_Strength = ARX_EQUIPMENT_Apply(
729 io, IO_EQUIPITEM_ELEMENT_STRENGTH, player.Attribute_Strength);
730 player.Mod_Attribute_Dexterity = ARX_EQUIPMENT_Apply(
731 io, IO_EQUIPITEM_ELEMENT_DEXTERITY, player.Attribute_Dexterity);
732 player.Mod_Attribute_Constitution = ARX_EQUIPMENT_Apply(
733 io, IO_EQUIPITEM_ELEMENT_CONSTITUTION, player.Attribute_Constitution);
734 player.Mod_Attribute_Mind = ARX_EQUIPMENT_Apply(
735 io, IO_EQUIPITEM_ELEMENT_MIND, player.Attribute_Mind);
736 player.Mod_armor_class = ARX_EQUIPMENT_Apply(
737 io, IO_EQUIPITEM_ELEMENT_Armor_Class, player.armor_class);
738
739 // Check for Equipment Modificators to Skills
740 player.Mod_Skill_Stealth = ARX_EQUIPMENT_Apply(
741 io, IO_EQUIPITEM_ELEMENT_Stealth, ARX_PLAYER_Get_Skill_Stealth(0));
742 player.Mod_Skill_Mecanism = ARX_EQUIPMENT_Apply(
743 io, IO_EQUIPITEM_ELEMENT_Mecanism, ARX_PLAYER_Get_Skill_Mecanism(0));
744 player.Mod_Skill_Intuition = ARX_EQUIPMENT_Apply(
745 io, IO_EQUIPITEM_ELEMENT_Intuition, ARX_PLAYER_Get_Skill_Intuition(0));
746 player.Mod_Skill_Etheral_Link = ARX_EQUIPMENT_Apply(
747 io, IO_EQUIPITEM_ELEMENT_Etheral_Link, ARX_PLAYER_Get_Skill_Etheral_Link(0));
748 player.Mod_Skill_Object_Knowledge = ARX_EQUIPMENT_Apply(
749 io, IO_EQUIPITEM_ELEMENT_Object_Knowledge, ARX_PLAYER_Get_Skill_Object_Knowledge(0));
750 player.Mod_Skill_Casting = ARX_EQUIPMENT_Apply(
751 io, IO_EQUIPITEM_ELEMENT_Casting, ARX_PLAYER_Get_Skill_Casting(0));
752 player.Mod_Skill_Projectile = ARX_EQUIPMENT_Apply(
753 io, IO_EQUIPITEM_ELEMENT_Projectile, ARX_PLAYER_Get_Skill_Projectile(0));
754 player.Mod_Skill_Close_Combat = ARX_EQUIPMENT_Apply(
755 io, IO_EQUIPITEM_ELEMENT_Close_Combat, ARX_PLAYER_Get_Skill_Close_Combat(0));
756 player.Mod_Skill_Defense = ARX_EQUIPMENT_Apply(
757 io, IO_EQUIPITEM_ELEMENT_Defense, ARX_PLAYER_Get_Skill_Defense(0));
758
759 player.Mod_resist_magic = ARX_EQUIPMENT_Apply(
760 io, IO_EQUIPITEM_ELEMENT_Resist_Magic, player.resist_magic);
761 player.Mod_resist_poison = ARX_EQUIPMENT_Apply(
762 io, IO_EQUIPITEM_ELEMENT_Resist_Poison, player.resist_poison);
763 player.Mod_Critical_Hit = ARX_EQUIPMENT_Apply(
764 io, IO_EQUIPITEM_ELEMENT_Critical_Hit, player.Critical_Hit);
765 player.Mod_damages = ARX_EQUIPMENT_Apply(
766 io, IO_EQUIPITEM_ELEMENT_Damages, 0);
767
768
769 //CHECK OVERFLOW
770 float fFullAimTime = ARX_EQUIPMENT_Apply(io, IO_EQUIPITEM_ELEMENT_AimTime, 0);
771 float fCalcHandicap = (player.Full_Attribute_Dexterity - 10.f) * 20.f;
772
773 //CAST
774 player.Full_AimTime = checked_range_cast<long>(fFullAimTime);
775
776 if (player.Full_AimTime <= 0) player.Full_AimTime = player.AimTime;
777
778 player.Full_AimTime -= checked_range_cast<long>(fCalcHandicap);
779
780
781 if (player.Full_AimTime <= 1500) player.Full_AimTime = 1500;
782
783
784
785 /// PERCENTILE.....
786 player.Mod_Attribute_Strength += ARX_EQUIPMENT_ApplyPercent(
787 io, IO_EQUIPITEM_ELEMENT_STRENGTH, player.Attribute_Strength + player.Mod_Attribute_Strength);
788 player.Mod_Attribute_Dexterity += ARX_EQUIPMENT_ApplyPercent(
789 io, IO_EQUIPITEM_ELEMENT_DEXTERITY, player.Attribute_Dexterity + player.Mod_Attribute_Dexterity);
790 player.Mod_Attribute_Constitution += ARX_EQUIPMENT_ApplyPercent(
791 io, IO_EQUIPITEM_ELEMENT_CONSTITUTION, player.Attribute_Constitution + player.Mod_Attribute_Constitution);
792 player.Mod_Attribute_Mind += ARX_EQUIPMENT_ApplyPercent(
793 io, IO_EQUIPITEM_ELEMENT_MIND, player.Attribute_Mind + player.Mod_Attribute_Mind);
794 player.Mod_armor_class += ARX_EQUIPMENT_ApplyPercent(
795 io, IO_EQUIPITEM_ELEMENT_Armor_Class, player.armor_class + player.Mod_armor_class);
796
797 // Check for Equipment Modificators to Skills
798 player.Mod_Skill_Stealth += ARX_EQUIPMENT_ApplyPercent(
799 io, IO_EQUIPITEM_ELEMENT_Stealth, ARX_PLAYER_Get_Skill_Stealth(1));
800 player.Mod_Skill_Mecanism += ARX_EQUIPMENT_ApplyPercent(
801 io, IO_EQUIPITEM_ELEMENT_Mecanism, ARX_PLAYER_Get_Skill_Mecanism(1));
802 player.Mod_Skill_Intuition += ARX_EQUIPMENT_ApplyPercent(
803 io, IO_EQUIPITEM_ELEMENT_Intuition, ARX_PLAYER_Get_Skill_Intuition(1));
804 player.Mod_Skill_Etheral_Link += ARX_EQUIPMENT_ApplyPercent(
805 io, IO_EQUIPITEM_ELEMENT_Etheral_Link, ARX_PLAYER_Get_Skill_Etheral_Link(1));
806 player.Mod_Skill_Object_Knowledge += ARX_EQUIPMENT_ApplyPercent(
807 io, IO_EQUIPITEM_ELEMENT_Object_Knowledge, ARX_PLAYER_Get_Skill_Object_Knowledge(1));
808 player.Mod_Skill_Casting += ARX_EQUIPMENT_ApplyPercent(
809 io, IO_EQUIPITEM_ELEMENT_Casting, ARX_PLAYER_Get_Skill_Casting(1));
810 player.Mod_Skill_Projectile += ARX_EQUIPMENT_ApplyPercent(
811 io, IO_EQUIPITEM_ELEMENT_Projectile, ARX_PLAYER_Get_Skill_Projectile(1));
812 player.Mod_Skill_Close_Combat += ARX_EQUIPMENT_ApplyPercent(
813 io, IO_EQUIPITEM_ELEMENT_Close_Combat, ARX_PLAYER_Get_Skill_Close_Combat(1));
814 player.Mod_Skill_Defense += ARX_EQUIPMENT_ApplyPercent(
815 io, IO_EQUIPITEM_ELEMENT_Defense, ARX_PLAYER_Get_Skill_Defense(1));
816
817 player.Mod_resist_magic += ARX_EQUIPMENT_ApplyPercent(
818 io, IO_EQUIPITEM_ELEMENT_Resist_Magic, player.resist_magic + player.Mod_resist_magic);
819 player.Mod_resist_poison += ARX_EQUIPMENT_ApplyPercent(
820 io, IO_EQUIPITEM_ELEMENT_Resist_Poison, player.resist_poison + player.Mod_resist_poison);
821 player.Mod_Critical_Hit += ARX_EQUIPMENT_ApplyPercent(
822 io, IO_EQUIPITEM_ELEMENT_Critical_Hit, player.Critical_Hit + player.Mod_Critical_Hit);
823 player.Mod_damages += ARX_EQUIPMENT_ApplyPercent(
824 io, IO_EQUIPITEM_ELEMENT_Damages, player.damages);
825 //player.Full_AimTime=ARX_EQUIPMENT_ApplyPercent(
826 // io,IO_EQUIPITEM_ELEMENT_AimTime,0);
827
828
829
830 // Check for Spell Modificators
831 if (entities.player())
832 for (long i = 0; i < entities.player()->nb_spells_on; i++)
833 {
834 long n = entities.player()->spells_on[i];
835
836 if (spells[n].exist)
837 {
838 switch (spells[n].type)
839 {
840 case SPELL_ARMOR:
841 player.Mod_armor_class += spells[n].caster_level;
842 break;
843 case SPELL_LOWER_ARMOR:
844 player.Mod_armor_class -= spells[n].caster_level;
845 break;
846 case SPELL_CURSE:
847 player.Mod_Attribute_Strength -= spells[n].caster_level;
848 player.Mod_Attribute_Constitution -= spells[n].caster_level;
849 player.Mod_Attribute_Dexterity -= spells[n].caster_level;
850 player.Mod_Attribute_Mind -= spells[n].caster_level;
851 break;
852 case SPELL_BLESS:
853 player.Mod_Attribute_Strength += spells[n].caster_level;
854 player.Mod_Attribute_Dexterity += spells[n].caster_level;
855 player.Mod_Attribute_Constitution += spells[n].caster_level;
856 player.Mod_Attribute_Mind += spells[n].caster_level;
857 break;
858 default: break;
859 }
860 }
861 }
862
863 if (cur_mr == 3)
864 {
865 player.Mod_Attribute_Strength += 1;
866 player.Mod_Attribute_Mind += 10;
867 player.Mod_Attribute_Constitution += 1;
868 player.Mod_Attribute_Dexterity += 10;
869 player.Mod_Skill_Stealth += 5;
870 player.Mod_Skill_Mecanism += 5;
871 player.Mod_Skill_Intuition += 100;
872 player.Mod_Skill_Etheral_Link += 100;
873 player.Mod_Skill_Object_Knowledge += 100;
874 player.Mod_Skill_Casting += 5;
875 player.Mod_Skill_Projectile += 5;
876 player.Mod_Skill_Close_Combat += 5;
877 player.Mod_Skill_Defense += 100;
878 player.Mod_resist_magic += 100;
879 player.Mod_resist_poison += 100;
880 player.Mod_Critical_Hit += 5;
881 player.Mod_damages += 2;
882 player.Mod_armor_class += 100;
883 player.Full_AimTime = 100;
884 }
885
886 if (sp_max)
887 {
888 player.Mod_Attribute_Strength += 5;
889 player.Mod_Attribute_Mind += 5;
890 player.Mod_Attribute_Constitution += 5;
891 player.Mod_Attribute_Dexterity += 5;
892 player.Mod_Skill_Stealth += 50;
893 player.Mod_Skill_Mecanism += 50;
894 player.Mod_Skill_Intuition += 50;
895 player.Mod_Skill_Etheral_Link += 50;
896 player.Mod_Skill_Object_Knowledge += 50;
897 player.Mod_Skill_Casting += 50;
898 player.Mod_Skill_Projectile += 50;
899 player.Mod_Skill_Close_Combat += 50;
900 player.Mod_Skill_Defense += 50;
901 player.Mod_resist_magic += 10;
902 player.Mod_resist_poison += 10;
903 player.Mod_Critical_Hit += 50;
904 player.Mod_damages += 10;
905 player.Mod_armor_class += 20;
906 player.Full_AimTime = 100;
907 }
908
909 if(SPECIAL_PNUX) {
910 player.Mod_Attribute_Strength += Random::get(0, 5);
911 player.Mod_Attribute_Mind += Random::get(0, 5);
912 player.Mod_Attribute_Constitution += Random::get(0, 5);
913 player.Mod_Attribute_Dexterity += Random::get(0, 5);
914 player.Mod_Skill_Stealth += Random::get(0, 20);
915 player.Mod_Skill_Mecanism += Random::get(0, 20);
916 player.Mod_Skill_Intuition += Random::get(0, 20);
917 player.Mod_Skill_Etheral_Link += Random::get(0, 20);
918 player.Mod_Skill_Object_Knowledge += Random::get(0, 20);
919 player.Mod_Skill_Casting += Random::get(0, 20);
920 player.Mod_Skill_Projectile += Random::get(0, 20);
921 player.Mod_Skill_Close_Combat += Random::get(0, 20);
922 player.Mod_Skill_Defense += Random::get(0, 30);
923 player.Mod_resist_magic += Random::get(0, 20);
924 player.Mod_resist_poison += Random::get(0, 20);
925 player.Mod_Critical_Hit += Random::get(0, 20);
926 player.Mod_damages += Random::get(0, 20);
927 player.Mod_armor_class += Random::get(0, 20);
928 }
929
930 if (cur_rf == 3)
931 {
932 player.Mod_Attribute_Mind += 10;
933 player.Mod_Skill_Casting += 100;
934 player.Mod_Skill_Etheral_Link += 100;
935 player.Mod_Skill_Object_Knowledge += 100;
936 player.Mod_resist_magic += 20;
937 player.Mod_resist_poison += 20;
938 player.Mod_damages += 1;
939 player.Mod_armor_class += 5;
940 }
941
942 player.Full_armor_class = player.armor_class + player.Mod_armor_class;
943
944 if (player.Full_armor_class < 0) player.Full_armor_class = 0;
945
946 player.Full_Attribute_Strength = player.Attribute_Strength + player.Mod_Attribute_Strength;
947
948 if (player.Full_Attribute_Strength < 0) player.Full_Attribute_Strength = 0;
949
950 player.Full_Attribute_Mind = player.Attribute_Mind + player.Mod_Attribute_Mind;
951
952 if (player.Full_Attribute_Mind < 0) player.Full_Attribute_Mind = 0;
953
954 player.Full_Attribute_Constitution = player.Attribute_Constitution + player.Mod_Attribute_Constitution;
955
956 if (player.Full_Attribute_Constitution < 0) player.Full_Attribute_Constitution = 0;
957
958 player.Full_Attribute_Dexterity = player.Attribute_Dexterity + player.Mod_Attribute_Dexterity;
959
960 if (player.Full_Attribute_Dexterity < 0) player.Full_Attribute_Dexterity = 0;
961
962 player.Full_Skill_Stealth = ARX_PLAYER_Get_Skill_Stealth(1);
963 player.Full_Skill_Mecanism = ARX_PLAYER_Get_Skill_Mecanism(1);
964 player.Full_Skill_Intuition = ARX_PLAYER_Get_Skill_Intuition(1);
965 player.Full_Skill_Etheral_Link = ARX_PLAYER_Get_Skill_Etheral_Link(1);
966 player.Full_Skill_Object_Knowledge = ARX_PLAYER_Get_Skill_Object_Knowledge(1);
967 player.Full_Skill_Casting = ARX_PLAYER_Get_Skill_Casting(1);
968 player.Full_Skill_Projectile = ARX_PLAYER_Get_Skill_Projectile(1);
969 player.Full_Skill_Close_Combat = ARX_PLAYER_Get_Skill_Close_Combat(1);
970 player.Full_Skill_Defense = ARX_PLAYER_Get_Skill_Defense(1);
971
972 player.Full_resist_magic = player.resist_magic + player.Mod_resist_magic;
973
974 if (player.Full_resist_magic < 0) player.Full_resist_magic = 0;
975
976 player.Full_resist_poison = player.resist_poison + player.Mod_resist_poison;
977
978 if (player.Full_resist_poison < 0) player.Full_resist_poison = 0;
979
980 player.Full_Critical_Hit = player.Critical_Hit + player.Mod_Critical_Hit;
981
982 if (player.Full_Critical_Hit < 0) player.Full_Critical_Hit = 0;
983
984 player.Full_damages = player.damages + player.Mod_damages
985 + player.Full_Skill_Close_Combat * ( 1.0f / 10 );
986
987 if (player.Full_damages < 1) player.Full_damages = 1;
988
989 player.Full_life = player.life;
990 player.Full_maxlife = (float)player.Full_Attribute_Constitution * (float)(player.level + 2);
991 player.life = std::min(player.life, player.Full_maxlife);
992 player.Full_maxmana = (float)player.Full_Attribute_Mind * (float)(player.level + 1);
993 player.mana = std::min(player.mana, player.Full_maxmana);
994 }
995
996 //*************************************************************************************
997 // void ARX_PLAYER_MakeFreshHero()
998 //-------------------------------------------------------------------------------------
999 // FUNCTION/RESULT:
1000 // Creates a Fresh hero
1001 //*************************************************************************************
ARX_PLAYER_MakeFreshHero()1002 void ARX_PLAYER_MakeFreshHero()
1003 {
1004 player.Attribute_Strength = 6;
1005 player.Attribute_Mind = 6;
1006 player.Attribute_Dexterity = 6;
1007 player.Attribute_Constitution = 6;
1008
1009 player.Old_Skill_Stealth = player.Skill_Stealth = 0;
1010 player.Old_Skill_Mecanism = player.Skill_Mecanism = 0;
1011 player.Old_Skill_Intuition = player.Skill_Intuition = 0;
1012 player.Old_Skill_Etheral_Link = player.Skill_Etheral_Link = 0;
1013 player.Old_Skill_Object_Knowledge = player.Skill_Object_Knowledge = 0;
1014 player.Old_Skill_Casting = player.Skill_Casting = 0;
1015 player.Old_Skill_Projectile = player.Skill_Projectile = 0;
1016 player.Old_Skill_Close_Combat = player.Skill_Close_Combat = 0;
1017 player.Old_Skill_Defense = player.Skill_Defense = 0;
1018
1019 player.Attribute_Redistribute = 16;
1020 player.Skill_Redistribute = 18;
1021
1022 player.level = 0;
1023 player.xp = 0;
1024 player.poison = 0.f;
1025 player.hunger = 100.f;
1026 player.skin = 0;
1027 player.bag = 1;
1028
1029 ARX_PLAYER_ComputePlayerStats();
1030 player.rune_flags = 0;
1031
1032 player.SpellToMemorize.bSpell = false;
1033 }
1034 char SKIN_MOD = 0;
1035 char QUICK_MOD = 0;
1036
ARX_SPSound()1037 void ARX_SPSound() {
1038 ARX_SOUND_PlayCinematic("kra_zoha_equip", false);
1039 }
1040
ARX_PLAYER_MakeSpHero()1041 void ARX_PLAYER_MakeSpHero()
1042 {
1043 ARX_SPSound();
1044 player.Attribute_Strength = 12;
1045 player.Attribute_Mind = 12;
1046 player.Attribute_Dexterity = 12;
1047 player.Attribute_Constitution = 12;
1048
1049 player.Old_Skill_Stealth = player.Skill_Stealth = 5;
1050 player.Old_Skill_Mecanism = player.Skill_Mecanism = 5;
1051 player.Old_Skill_Intuition = player.Skill_Intuition = 5;
1052 player.Old_Skill_Etheral_Link = player.Skill_Etheral_Link = 5;
1053 player.Old_Skill_Object_Knowledge = player.Skill_Object_Knowledge = 5;
1054 player.Old_Skill_Casting = player.Skill_Casting = 5;
1055 player.Old_Skill_Projectile = player.Skill_Projectile = 5;
1056 player.Old_Skill_Close_Combat = player.Skill_Close_Combat = 5;
1057 player.Old_Skill_Defense = player.Skill_Defense = 5;
1058
1059 player.Attribute_Redistribute = 6;
1060 player.Skill_Redistribute = 10;
1061
1062 player.level = 1;
1063 player.xp = 0;
1064 player.poison = 0.f;
1065 player.hunger = 100.f;
1066 player.skin = 4;
1067
1068 ARX_PLAYER_ComputePlayerStats();
1069 player.life = player.maxlife;
1070 player.mana = player.maxmana;
1071
1072 player.rune_flags = RuneFlags::all();
1073 player.SpellToMemorize.bSpell = false;
1074
1075 SKIN_MOD = 0;
1076 QUICK_MOD = 0;
1077 }
1078 //*************************************************************************************
1079 // void ARX_PLAYER_MakePowerfullHero()
1080 //-------------------------------------------------------------------------------------
1081 // FUNCTION/RESULT:
1082 // Creates a POWERFULL hero
1083 //*************************************************************************************
ARX_PLAYER_MakePowerfullHero()1084 void ARX_PLAYER_MakePowerfullHero()
1085 {
1086 player.Attribute_Strength = 18;
1087 player.Attribute_Mind = 18;
1088 player.Attribute_Dexterity = 18;
1089 player.Attribute_Constitution = 18;
1090
1091 player.Old_Skill_Stealth = player.Skill_Stealth = 82;
1092 player.Old_Skill_Mecanism = player.Skill_Mecanism = 82;
1093 player.Old_Skill_Intuition = player.Skill_Intuition = 82;
1094 player.Old_Skill_Etheral_Link = player.Skill_Etheral_Link = 82;
1095 player.Old_Skill_Object_Knowledge = player.Skill_Object_Knowledge = 82;
1096 player.Old_Skill_Casting = player.Skill_Casting = 82;
1097 player.Old_Skill_Projectile = player.Skill_Projectile = 82;
1098 player.Old_Skill_Close_Combat = player.Skill_Close_Combat = 82;
1099 player.Old_Skill_Defense = player.Skill_Defense = 82;
1100
1101 player.Attribute_Redistribute = 0;
1102 player.Skill_Redistribute = 0;
1103
1104 player.level = 10;
1105 player.xp = 178000;
1106 player.poison = 0.f;
1107 player.hunger = 100.f;
1108 player.skin = 0;
1109
1110 ARX_PLAYER_ComputePlayerStats();
1111 player.life = player.maxlife;
1112 player.mana = player.maxmana;
1113
1114 player.rune_flags = RuneFlags::all();
1115 player.SpellToMemorize.bSpell = false;
1116 }
1117
1118 //*************************************************************************************
1119 // void ARX_PLAYER_MakeAverageHero()
1120 //-------------------------------------------------------------------------------------
1121 // FUNCTION/RESULT:
1122 // Creates an Average hero
1123 //*************************************************************************************
ARX_PLAYER_MakeAverageHero()1124 void ARX_PLAYER_MakeAverageHero()
1125 {
1126 ARX_PLAYER_MakeFreshHero();
1127
1128 player.Attribute_Strength += 4;
1129 player.Attribute_Mind += 4;
1130 player.Attribute_Dexterity += 4;
1131 player.Attribute_Constitution += 4;
1132
1133 player.Skill_Stealth += 2;
1134 player.Skill_Mecanism += 2;
1135 player.Skill_Intuition += 2;
1136 player.Skill_Etheral_Link += 2;
1137 player.Skill_Object_Knowledge += 2;
1138 player.Skill_Casting += 2;
1139 player.Skill_Projectile += 2;
1140 player.Skill_Close_Combat += 2;
1141 player.Skill_Defense += 2;
1142
1143 player.Attribute_Redistribute = 0;
1144 player.Skill_Redistribute = 0;
1145
1146 player.level = 0;
1147 player.xp = 0;
1148 player.hunger = 100.f;
1149
1150 ARX_PLAYER_ComputePlayerStats();
1151 }
1152
1153 //*************************************************************************************
1154 // void ARX_PLAYER_QuickGeneration()
1155 //-------------------------------------------------------------------------------------
1156 // FUNCTION/RESULT:
1157 // Quickgenerate a random hero
1158 //*************************************************************************************
ARX_PLAYER_QuickGeneration()1159 void ARX_PLAYER_QuickGeneration() {
1160
1161 char old_skin = player.skin;
1162 ARX_PLAYER_MakeFreshHero();
1163 player.skin = old_skin;
1164
1165 while (player.Attribute_Redistribute)
1166 {
1167 float rn = rnd();
1168
1169 if ((rn < 0.25f) && (player.Attribute_Strength < 18))
1170 {
1171 player.Attribute_Strength++;
1172 player.Attribute_Redistribute--;
1173 }
1174 else if ((rn < 0.5f) && (player.Attribute_Mind < 18))
1175 {
1176 player.Attribute_Mind++;
1177 player.Attribute_Redistribute--;
1178 }
1179 else if ((rn < 0.75f) && (player.Attribute_Dexterity < 18))
1180 {
1181 player.Attribute_Dexterity++;
1182 player.Attribute_Redistribute--;
1183 }
1184 else if (player.Attribute_Constitution < 18)
1185 {
1186 player.Attribute_Constitution++;
1187 player.Attribute_Redistribute--;
1188 }
1189 }
1190
1191 while (player.Skill_Redistribute)
1192 {
1193 float rn = rnd();
1194
1195 if ((rn < 0.1f) && (player.Skill_Stealth < 18))
1196 {
1197 player.Skill_Stealth++;
1198 player.Skill_Redistribute--;
1199 }
1200 else if ((rn < 0.2f) && (player.Skill_Mecanism < 18))
1201 {
1202 player.Skill_Mecanism++;
1203 player.Skill_Redistribute--;
1204 }
1205 else if ((rn < 0.3f) && (player.Skill_Intuition < 18))
1206 {
1207 player.Skill_Intuition++;
1208 player.Skill_Redistribute--;
1209 }
1210 else if ((rn < 0.4f) && (player.Skill_Etheral_Link < 18))
1211 {
1212 player.Skill_Etheral_Link++;
1213 player.Skill_Redistribute--;
1214 }
1215 else if ((rn < 0.5f) && (player.Skill_Object_Knowledge < 18))
1216 {
1217 player.Skill_Object_Knowledge++;
1218 player.Skill_Redistribute--;
1219 }
1220 else if ((rn < 0.6f) && (player.Skill_Casting < 18))
1221 {
1222 player.Skill_Casting++;
1223 player.Skill_Redistribute--;
1224 }
1225 else if ((rn < 0.7f) && (player.Skill_Projectile < 18))
1226 {
1227 player.Skill_Projectile++;
1228 player.Skill_Redistribute--;
1229 }
1230 else if ((rn < 0.8f) && (player.Skill_Close_Combat < 18))
1231 {
1232 player.Skill_Close_Combat++;
1233 player.Skill_Redistribute--;
1234 }
1235 else if ((rn < 0.9f) && (player.Skill_Defense < 18))
1236 {
1237 player.Skill_Defense++;
1238 player.Skill_Redistribute--;
1239 }
1240 }
1241
1242 player.level = 0;
1243 player.xp = 0;
1244 player.hunger = 100.f;
1245
1246 ARX_PLAYER_ComputePlayerStats();
1247 }
1248
1249 //*************************************************************************************
1250 // long GetXPforLevel(long level)
1251 //-------------------------------------------------------------------------------------
1252 // FUNCTION/RESULT:
1253 // Returns necessary Experience for a given level
1254 //*************************************************************************************
GetXPforLevel(long level)1255 long GetXPforLevel(long level)
1256 {
1257 const long XP_FOR_LEVEL[] = {
1258 0,
1259 2000,
1260 4000,
1261 6000,
1262 10000,
1263 16000,
1264 26000,
1265 42000,
1266 68000,
1267 110000,
1268 178000,
1269 300000,
1270 450000,
1271 600000,
1272 750000
1273 };
1274
1275 long xpNeeded;
1276 if(level < (long)ARRAY_SIZE(XP_FOR_LEVEL))
1277 xpNeeded = XP_FOR_LEVEL[level];
1278 else
1279 xpNeeded = level * 60000;
1280 return xpNeeded;
1281 }
1282
1283 //*************************************************************************************
1284 // void ARX_PLAYER_LEVEL_UP()
1285 //-------------------------------------------------------------------------------------
1286 // FUNCTION/RESULT:
1287 // Manages Player Level Up event
1288 //*************************************************************************************
ARX_PLAYER_LEVEL_UP()1289 void ARX_PLAYER_LEVEL_UP()
1290 {
1291 ARX_SOUND_PlayInterface(SND_PLAYER_LEVEL_UP);
1292 player.level++;
1293 player.Skill_Redistribute += 15;
1294 player.Attribute_Redistribute++;
1295 ARX_PLAYER_ComputePlayerStats();
1296 player.life = player.maxlife;
1297 player.mana = player.maxmana;
1298 player.Old_Skill_Stealth = player.Skill_Stealth;
1299 player.Old_Skill_Mecanism = player.Skill_Mecanism;
1300 player.Old_Skill_Intuition = player.Skill_Intuition;
1301 player.Old_Skill_Etheral_Link = player.Skill_Etheral_Link;
1302 player.Old_Skill_Object_Knowledge = player.Skill_Object_Knowledge;
1303 player.Old_Skill_Casting = player.Skill_Casting;
1304 player.Old_Skill_Projectile = player.Skill_Projectile;
1305 player.Old_Skill_Close_Combat = player.Skill_Close_Combat;
1306 player.Old_Skill_Defense = player.Skill_Defense;
1307 SendIOScriptEvent(entities.player(), SM_NULL, "", "level_up");
1308 }
1309
1310 //*************************************************************************************
1311 // void ARX_PLAYER_Modify_XP(long val)
1312 //-------------------------------------------------------------------------------------
1313 // FUNCTION/RESULT:
1314 // Modify player XP by adding "val" to it
1315 //*************************************************************************************
ARX_PLAYER_Modify_XP(long val)1316 void ARX_PLAYER_Modify_XP(long val) {
1317
1318 player.xp += val;
1319
1320 for (long i = player.level + 1; i < 11; i++) {
1321 if(player.xp >= GetXPforLevel(i)) {
1322 ARX_PLAYER_LEVEL_UP();
1323 }
1324 }
1325 }
1326
1327 //*************************************************************************************
1328 // void ARX_PLAYER_Poison(float val)
1329 //-------------------------------------------------------------------------------------
1330 // FUNCTION/RESULT:
1331 // Function to poison player by "val" poison level
1332 //*************************************************************************************
ARX_PLAYER_Poison(float val)1333 void ARX_PLAYER_Poison(float val)
1334 {
1335 // Make a poison saving throw to see if player is affected
1336 if (rnd() * 100.f > player.resist_poison)
1337 {
1338 player.poison += val;
1339 ARX_SOUND_PlayInterface(SND_PLAYER_POISONED);
1340 }
1341 }
1342 long PLAYER_PARALYSED = 0;
1343
1344 // FUNCTION/RESULT:
1345 // updates some player stats depending on time:
1346 // .life/mana recovery
1347 // .poison evolution
1348 // .hunger check
1349 // .invisibility
ARX_PLAYER_FrameCheck(float Framedelay)1350 void ARX_PLAYER_FrameCheck(float Framedelay)
1351 {
1352 // ARX_PLAYER_QuickGeneration();
1353 if (Framedelay > 0)
1354 {
1355 UpdateIOInvisibility(entities.player());
1356 // Natural LIFE recovery
1357 float inc = 0.00008f * Framedelay * (player.Full_Attribute_Constitution + player.Full_Attribute_Strength * ( 1.0f / 2 ) + player.Full_Skill_Defense) * ( 1.0f / 50 );
1358
1359 if (player.life > 0.f)
1360 {
1361 float inc_hunger = 0.00008f * Framedelay * (player.Full_Attribute_Constitution + player.Full_Attribute_Strength * ( 1.0f / 2 )) * ( 1.0f / 50 );
1362
1363 // Check for player hungry sample playing
1364 if (((player.hunger > 10.f) && (player.hunger - inc_hunger <= 10.f))
1365 || ((player.hunger < 10.f) && (float(arxtime) > LastHungerSample + 180000)))
1366 {
1367 LastHungerSample = (unsigned long)(arxtime);
1368
1369 if (!BLOCK_PLAYER_CONTROLS)
1370 {
1371 bool bOk = true;
1372
1373 for(size_t i = 0; i < MAX_ASPEECH; i++) {
1374 if(aspeech[i].exist && (aspeech[i].io == entities.player())) {
1375 bOk = false;
1376 }
1377 }
1378
1379 if (bOk)
1380 ARX_SPEECH_AddSpeech(entities.player(), "player_off_hungry", ANIM_TALK_NEUTRAL, ARX_SPEECH_FLAG_NOTEXT);
1381 }
1382 }
1383
1384 player.hunger -= inc_hunger * .5f; //*.7f;
1385
1386 if (player.hunger < -10.f) player.hunger = -10.f;
1387
1388 if (!BLOCK_PLAYER_CONTROLS)
1389 {
1390 if (player.hunger < 0.f) player.life -= inc * ( 1.0f / 2 );
1391 else player.life += inc;
1392 }
1393
1394 // Natural MANA recovery
1395 player.mana += 0.00008f * Framedelay * ((player.Full_Attribute_Mind + player.Full_Skill_Etheral_Link) * 10) * ( 1.0f / 100 ); //framedelay*( 1.0f / 1000 );
1396
1397 if (player.mana > player.Full_maxmana) player.mana = player.Full_maxmana;
1398 }
1399
1400 //float pmaxlife=(float)player.Full_Attribute_Constitution*(float)(player.level+2);
1401 if (player.life > player.Full_maxlife) player.life = player.Full_maxlife;
1402
1403 // Now Checks Poison Progression
1404 if (!BLOCK_PLAYER_CONTROLS)
1405 if (player.poison > 0.f)
1406 {
1407 float cp = player.poison;
1408 cp *= ( 1.0f / 2 ) * Framedelay * ( 1.0f / 1000 ) * ( 1.0f / 2 );
1409 float faster = 10.f - player.poison;
1410
1411 if (faster < 0.f) faster = 0.f;
1412
1413 if (rnd() * 100.f > player.resist_poison + faster)
1414 {
1415 float dmg = cp * ( 1.0f / 3 );
1416
1417 if (player.life - dmg <= 0.f) ARX_DAMAGES_DamagePlayer(dmg, DAMAGE_TYPE_POISON, -1);
1418 else player.life -= dmg;
1419
1420 player.poison -= cp * ( 1.0f / 10 );
1421 }
1422 else player.poison -= cp;
1423 }
1424
1425 if (player.poison < 0.1f) player.poison = 0.f;
1426 }
1427 }
1428 TextureContainer * PLAYER_SKIN_TC = NULL;
1429
ARX_PLAYER_Restore_Skin()1430 void ARX_PLAYER_Restore_Skin() {
1431
1432 res::path tx;
1433 res::path tx2;
1434 res::path tx3;
1435 res::path tx4;
1436
1437 switch(player.skin) {
1438 case 0:
1439 tx = "graph/obj3d/textures/npc_human_base_hero_head";
1440 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero_head";
1441 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero_head";
1442 tx4 = "graph/obj3d/textures/npc_human_leather_hero_head";
1443 break;
1444 case 1:
1445 tx = "graph/obj3d/textures/npc_human_base_hero2_head";
1446 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero2_head";
1447 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero2_head";
1448 tx4 = "graph/obj3d/textures/npc_human_leather_hero2_head";
1449 break;
1450 case 2:
1451 tx = "graph/obj3d/textures/npc_human_base_hero3_head";
1452 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero3_head";
1453 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero3_head";
1454 tx4 = "graph/obj3d/textures/npc_human_leather_hero3_head";
1455 break;
1456 case 3:
1457 tx = "graph/obj3d/textures/npc_human_base_hero4_head";
1458 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero4_head";
1459 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero4_head";
1460 tx4 = "graph/obj3d/textures/npc_human_leather_hero4_head";
1461 break;
1462 case 4:
1463 tx = "graph/obj3d/textures/npc_human_cm_hero_head";
1464 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero_head";
1465 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero_head";
1466 tx4 = "graph/obj3d/textures/npc_human_leather_hero_head";
1467 break;
1468 case 5:
1469 tx = "graph/obj3d/textures/npc_human__base_hero_head";
1470 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero_head";
1471 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero_head";
1472 tx4 = "graph/obj3d/textures/npc_human_leather_hero_head";
1473 break;
1474 case 6: //just in case
1475 tx = "graph/obj3d/textures/npc_human__base_hero_head";
1476 tx2 = "graph/obj3d/textures/npc_human_chainmail_hero_head";
1477 tx3 = "graph/obj3d/textures/npc_human_chainmail_mithril_hero_head";
1478 tx4 = "graph/obj3d/textures/npc_human_leather_hero_head";
1479 break;
1480 }
1481
1482 TextureContainer * tmpTC;
1483
1484 // TODO maybe it would be better to replace the textures in the player object instead of replacing the texture data for all objects that use these textures
1485
1486 if (PLAYER_SKIN_TC && !tx.empty())
1487 PLAYER_SKIN_TC->LoadFile(tx);
1488
1489 tmpTC = TextureContainer::Find("graph/obj3d/textures/npc_human_chainmail_hero_head");
1490 if (tmpTC && !tx2.empty())
1491 tmpTC->LoadFile(tx2);
1492
1493 tmpTC = TextureContainer::Find("graph/obj3d/textures/npc_human_chainmail_mithril_hero_head");
1494 if (tmpTC && !tx3.empty())
1495 tmpTC->LoadFile(tx3);
1496
1497 tmpTC = TextureContainer::Find("graph/obj3d/textures/npc_human_leather_hero_head");
1498 if (tmpTC && !tx4.empty())
1499 tmpTC->LoadFile(tx4);
1500 }
1501
1502 //Load Mesh & anims for hero
ARX_PLAYER_LoadHeroAnimsAndMesh()1503 void ARX_PLAYER_LoadHeroAnimsAndMesh(){
1504
1505 const char OBJECT_HUMAN_BASE[] = "graph/obj3d/interactive/npc/human_base/human_base.teo";
1506 hero = loadObject(OBJECT_HUMAN_BASE, false);
1507 PLAYER_SKIN_TC = TextureContainer::Load("graph/obj3d/textures/npc_human_base_hero_head");
1508
1509 const char ANIM_WAIT_BOOK[] = "graph/obj3d/anims/npc/human_wait_book.tea";
1510 herowaitbook = EERIE_ANIMMANAGER_Load(ANIM_WAIT_BOOK);
1511 const char ANIM_WAIT_NORMAL[] = "graph/obj3d/anims/npc/human_normal_wait.tea";
1512 EERIE_ANIMMANAGER_Load(ANIM_WAIT_NORMAL);
1513 const char ANIM_WAIT_TWOHANDED[] = "graph/obj3d/anims/npc/human_wait_book_2handed.tea";
1514 herowait_2h = EERIE_ANIMMANAGER_Load(ANIM_WAIT_TWOHANDED);
1515
1516 Entity * io = new Entity("graph/obj3d/interactive/player/player");
1517 arx_assert_msg(io->index() == 0, "player entity didn't get index 0");
1518 arx_assert(entities.player() == io);
1519
1520 io->obj = hero;
1521
1522 player.skin = 0;
1523 ARX_PLAYER_Restore_Skin();
1524
1525 ARX_INTERACTIVE_Show_Hide_1st(entities.player(), 0);
1526 ARX_INTERACTIVE_HideGore(entities.player(), 1);
1527 io->ident = -1;
1528
1529 //todo free
1530 io->_npcdata = new IO_NPCDATA;
1531
1532 io->ioflags = IO_NPC;
1533 io->_npcdata->maxlife = io->_npcdata->life = 10.f;
1534 io->_npcdata->vvpos = -99999.f;
1535
1536 //todo free
1537 io->armormaterial = "leather";
1538 loadScript(io->script, resources->getFile("graph/obj3d/interactive/player/player.asl"));
1539
1540 if ((EERIE_OBJECT_GetGroup(io->obj, "head") != -1)
1541 && (EERIE_OBJECT_GetGroup(io->obj, "neck") != -1)
1542 && (EERIE_OBJECT_GetGroup(io->obj, "chest") != -1)
1543 && (EERIE_OBJECT_GetGroup(io->obj, "belt") != -1))
1544 {
1545 io->_npcdata->ex_rotate = (EERIE_EXTRA_ROTATE *)malloc(sizeof(EERIE_EXTRA_ROTATE));
1546
1547 if(io->_npcdata->ex_rotate)
1548 {
1549 io->_npcdata->ex_rotate->group_number[0] = (short)EERIE_OBJECT_GetGroup(io->obj, "head");
1550 io->_npcdata->ex_rotate->group_number[1] = (short)EERIE_OBJECT_GetGroup(io->obj, "neck");
1551 io->_npcdata->ex_rotate->group_number[2] = (short)EERIE_OBJECT_GetGroup(io->obj, "chest");
1552 io->_npcdata->ex_rotate->group_number[3] = (short)EERIE_OBJECT_GetGroup(io->obj, "belt");
1553
1554 for (long n = 0; n < MAX_EXTRA_ROTATE; n++)
1555 {
1556 io->_npcdata->ex_rotate->group_rotate[n] = Anglef::ZERO;
1557 }
1558
1559 io->_npcdata->ex_rotate->flags = 0;
1560 }
1561 }
1562
1563 ARX_INTERACTIVE_RemoveGoreOnIO(entities.player());
1564 }
1565 float Falling_Height = 0;
ARX_PLAYER_StartFall()1566 void ARX_PLAYER_StartFall()
1567 {
1568 FALLING_TIME = 1;
1569 Falling_Height = 50.f;
1570 float yy;
1571 EERIEPOLY * ep = CheckInPoly(player.pos.x, player.pos.y, player.pos.z, &yy);
1572
1573 if (ep)
1574 {
1575 Falling_Height = player.pos.y;
1576 }
1577 }
1578
1579 //*************************************************************************************
1580 // void ARX_PLAYER_BecomesDead()
1581 //-------------------------------------------------------------------------------------
1582 // FUNCTION/RESULT:
1583 // Called When player has just died
1584 //*************************************************************************************
ARX_PLAYER_BecomesDead()1585 void ARX_PLAYER_BecomesDead()
1586 {
1587 STARTED_A_GAME = 0;
1588 // a mettre au final
1589 BLOCK_PLAYER_CONTROLS = 1;
1590
1591 if (entities.player())
1592 {
1593 player.Interface &= ~INTER_COMBATMODE;
1594 player.Interface = 0;
1595 DeadCameraDistance = 40.f;
1596 DeadTime = 0;
1597 }
1598
1599 for(size_t i = 0; i < MAX_SPELLS; i++) {
1600 if(spells[i].exist && spells[i].caster == 0) {
1601 spells[i].tolive = 0;
1602 }
1603 }
1604 }
1605
1606 float LASTPLAYERA = 0;
1607 extern long ON_PLATFORM;
1608 long LAST_ON_PLATFORM = 0;
1609 extern long MOVE_PRECEDENCE;
1610 extern long EXTERNALVIEW;
1611
1612 // Manages Player visual
1613 // Choose the set of animations to use to represent current player
1614 // situation.
ARX_PLAYER_Manage_Visual()1615 void ARX_PLAYER_Manage_Visual() {
1616
1617 unsigned long tim = (unsigned long)(arxtime);
1618
1619 if(player.Current_Movement & PLAYER_ROTATE) {
1620 if(ROTATE_START == 0) {
1621 ROTATE_START = tim;
1622 }
1623 } else if (ROTATE_START) {
1624 float diff = (float)tim - (float)ROTATE_START;
1625 if(diff > 100) {
1626 ROTATE_START = 0;
1627 }
1628 }
1629
1630 static long special[3];
1631 long light = 0;
1632
1633 if(entities.player()) {
1634
1635 Entity * io = entities.player();
1636
1637 if(!BLOCK_PLAYER_CONTROLS && sp_max) {
1638 io->halo.color = Color3f::red;
1639 io->halo.flags |= HALO_ACTIVE | HALO_DYNLIGHT;
1640 io->halo.radius = 20.f;
1641 player.life += float(FrameDiff) * 0.1f;
1642 player.life = std::min(player.life, player.maxlife);
1643 player.mana += float(FrameDiff) * 0.1f;
1644 player.mana = std::min(player.mana, player.maxmana);
1645 }
1646
1647 if(cur_mr == 3) {
1648 player.life += float(FrameDiff) * 0.05f;
1649 player.life = std::min(player.life, player.maxlife);
1650 player.mana += float(FrameDiff) * 0.05f;
1651 player.mana = std::min(player.mana, player.maxmana);
1652 }
1653
1654 io->pos = player.basePosition();
1655
1656 if(player.jumpphase == NotJumping && !LAST_ON_PLATFORM) {
1657 float t;
1658 EERIEPOLY * ep = CheckInPolyPrecis(player.pos.x, player.pos.y, player.pos.z, &t);
1659 if(ep && io->pos.y > t - 30.f && io->pos.y < t) {
1660 player.onfirmground = 1;
1661 }
1662 }
1663
1664 ComputeVVPos(io);
1665 io->pos.y = io->_npcdata->vvpos;
1666
1667 if(!(player.Current_Movement & PLAYER_CROUCH) && player.physics.cyl.height > -150.f) {
1668 float old = player.physics.cyl.height;
1669 player.physics.cyl.height = player.baseHeight();
1670 player.physics.cyl.origin = player.basePosition();
1671 float anything = CheckAnythingInCylinder(&player.physics.cyl, entities.player());
1672 if(anything < 0.f) {
1673 player.Current_Movement |= PLAYER_CROUCH;
1674 player.physics.cyl.height = old;
1675 }
1676 }
1677
1678 if(player.life > 0) {
1679 io->angle = Anglef(0.f, 180.f - player.angle.b, 0.f);
1680 }
1681
1682 io->gameFlags |= GFLAG_ISINTREATZONE;
1683
1684 ANIM_USE * ause0 = &io->animlayer[0];
1685 ANIM_USE * ause1 = &io->animlayer[1];
1686 ANIM_USE * ause3 = &io->animlayer[3];
1687
1688 ause0->next_anim = NULL;
1689 entities.player()->animlayer[1].next_anim = NULL;
1690 entities.player()->animlayer[2].next_anim = NULL;
1691 entities.player()->animlayer[3].next_anim = NULL;
1692 ANIM_HANDLE ** alist = io->anims;
1693
1694 if(ause0->flags & EA_FORCEPLAY) {
1695 if(ause0->flags & EA_ANIMEND) {
1696 ause0->flags &= ~EA_FORCEPLAY;
1697 ause0->flags |= EA_STATICANIM;
1698 io->move = io->lastmove = Vec3f::ZERO;
1699 } else {
1700 ause0->flags &= ~EA_STATICANIM;
1701 player.pos = moveto = player.pos + io->move;
1702 io->pos = player.basePosition();
1703 goto nochanges;
1704 }
1705 }
1706
1707 ANIM_HANDLE * ChangeMoveAnim = NULL;
1708 ANIM_HANDLE * ChangeMoveAnim2 = NULL;
1709 long ChangeMA_Loop = 1;
1710 long ChangeMA_Stopend = 0;
1711
1712 if(io->ioflags & IO_FREEZESCRIPT) {
1713 goto nochanges;
1714 }
1715
1716 if(player.life <= 0) {
1717 HERO_SHOW_1ST = -1;
1718 io->animlayer[1].cur_anim = NULL;
1719 ChangeMoveAnim = alist[ANIM_DIE];
1720 ChangeMA_Loop = 0;
1721 ChangeMA_Stopend = 1;
1722 goto makechanges;
1723 }
1724
1725 if(player.Current_Movement == 0 || player.Current_Movement == PLAYER_MOVE_STEALTH
1726 || (player.Current_Movement & PLAYER_ROTATE)) {
1727 if(player.Interface & INTER_COMBATMODE) {
1728 ChangeMoveAnim = alist[ANIM_FIGHT_WAIT];
1729 } else if(EXTERNALVIEW) {
1730 ChangeMoveAnim = alist[ANIM_WAIT];
1731 } else {
1732 ChangeMoveAnim = alist[ANIM_WAIT_SHORT];
1733 }
1734 ChangeMA_Loop = 1;
1735 }
1736
1737 if(ROTATE_START && player.angle.a > 60.f && player.angle.a < 180.f
1738 && LASTPLAYERA > 60.f && LASTPLAYERA < 180.f) {
1739 if (PLAYER_ROTATION < 0)
1740 {
1741 if (player.Interface & INTER_COMBATMODE)
1742 ChangeMoveAnim = alist[ANIM_U_TURN_LEFT_FIGHT];
1743 else ChangeMoveAnim = alist[ANIM_U_TURN_LEFT];
1744 }
1745 else
1746 {
1747 if (player.Interface & INTER_COMBATMODE)
1748 ChangeMoveAnim = alist[ANIM_U_TURN_RIGHT_FIGHT];
1749 else ChangeMoveAnim = alist[ANIM_U_TURN_RIGHT];
1750 }
1751
1752 ChangeMA_Loop = 1;
1753
1754 if ((ause0->cur_anim == alist[ANIM_U_TURN_LEFT])
1755 || (ause0->cur_anim == alist[ANIM_U_TURN_LEFT_FIGHT]))
1756 {
1757 float fv = PLAYER_ROTATION * 5;
1758 long vv = fv;
1759 io->frameloss -= fv - (float)vv;
1760
1761 if (io->frameloss < 0) io->frameloss = 0;
1762
1763 ause0->ctime -= vv;
1764
1765 if (ause0->ctime < 0)
1766 ause0->ctime = 0;
1767 }
1768 else if ((ause0->cur_anim == alist[ANIM_U_TURN_RIGHT])
1769 || (ause0->cur_anim == alist[ANIM_U_TURN_RIGHT_FIGHT]))
1770 {
1771 long vv = PLAYER_ROTATION * 5;
1772 float fv = PLAYER_ROTATION * 5;
1773 io->frameloss += fv - (float)vv;
1774
1775 if (io->frameloss < 0) io->frameloss = 0;
1776
1777 ause0->ctime += vv;
1778
1779 if (ause0->ctime < 0)
1780 ause0->ctime = 0;
1781 }
1782 }
1783
1784 LASTPLAYERA = player.angle.a;
1785
1786 {
1787 long tmove = player.Current_Movement;
1788
1789 if (((tmove & PLAYER_MOVE_STRAFE_LEFT)
1790 && (tmove & PLAYER_MOVE_STRAFE_RIGHT)))
1791 {
1792 tmove &= ~PLAYER_MOVE_STRAFE_LEFT;
1793 tmove &= ~PLAYER_MOVE_STRAFE_RIGHT;
1794 }
1795
1796 if (MOVE_PRECEDENCE == PLAYER_MOVE_STRAFE_LEFT)
1797 tmove &= ~PLAYER_MOVE_STRAFE_RIGHT;
1798
1799 if (MOVE_PRECEDENCE == PLAYER_MOVE_STRAFE_RIGHT)
1800 tmove &= ~PLAYER_MOVE_STRAFE_LEFT;
1801
1802 if (MOVE_PRECEDENCE == PLAYER_MOVE_WALK_FORWARD)
1803 tmove &= ~PLAYER_MOVE_WALK_BACKWARD;
1804
1805 if (player.Current_Movement & PLAYER_MOVE_WALK_FORWARD)
1806 tmove = PLAYER_MOVE_WALK_FORWARD;
1807
1808 {
1809 if (tmove & PLAYER_MOVE_STRAFE_LEFT)
1810 {
1811 if (player.Interface & INTER_COMBATMODE)
1812 ChangeMoveAnim = alist[ANIM_FIGHT_STRAFE_LEFT];
1813 else if (player.Current_Movement & PLAYER_MOVE_STEALTH)
1814 ChangeMoveAnim = alist[ANIM_STRAFE_LEFT];
1815 else
1816 ChangeMoveAnim = alist[ANIM_STRAFE_RUN_LEFT];
1817 }
1818
1819 if (tmove & PLAYER_MOVE_STRAFE_RIGHT)
1820 {
1821 if (player.Interface & INTER_COMBATMODE)
1822 ChangeMoveAnim = alist[ANIM_FIGHT_STRAFE_RIGHT];
1823 else if (player.Current_Movement & PLAYER_MOVE_STEALTH)
1824 ChangeMoveAnim = alist[ANIM_STRAFE_RIGHT];
1825 else
1826 ChangeMoveAnim = alist[ANIM_STRAFE_RUN_RIGHT];
1827 }
1828 }
1829
1830 if (tmove & PLAYER_MOVE_WALK_BACKWARD)
1831 {
1832 if (player.Interface & INTER_COMBATMODE)
1833 ChangeMoveAnim = alist[ANIM_FIGHT_WALK_BACKWARD];
1834 else if (player.Current_Movement & PLAYER_MOVE_STEALTH)
1835 ChangeMoveAnim = alist[ANIM_WALK_BACKWARD];
1836 else if (player.Current_Movement & PLAYER_CROUCH)
1837 ChangeMoveAnim = alist[ANIM_WALK_BACKWARD];
1838 else
1839 ChangeMoveAnim = alist[ANIM_RUN_BACKWARD];
1840 }
1841
1842 if (tmove & PLAYER_MOVE_WALK_FORWARD)
1843 {
1844
1845 if (player.Interface & INTER_COMBATMODE)
1846 ChangeMoveAnim = alist[ANIM_FIGHT_WALK_FORWARD];
1847 else if (player.Current_Movement & PLAYER_MOVE_STEALTH)
1848 ChangeMoveAnim = alist[ANIM_WALK];
1849 else
1850 ChangeMoveAnim = alist[ANIM_RUN];
1851 }
1852
1853 }
1854
1855 if (ChangeMoveAnim == NULL)
1856 {
1857 if (EXTERNALVIEW)
1858 ChangeMoveAnim = alist[ANIM_WAIT];
1859 else
1860 ChangeMoveAnim = alist[ANIM_WAIT_SHORT];
1861
1862 ChangeMA_Loop = 1;
1863 }
1864
1865 // Finally update anim
1866 if ((ause1->cur_anim == NULL)
1867 && ((ause0->cur_anim == alist[ANIM_WAIT])
1868 || (ause0->cur_anim == alist[ANIM_WAIT_SHORT]))
1869 && (!(player.Current_Movement & PLAYER_CROUCH)))
1870 {
1871 if ((player.Current_Movement & PLAYER_LEAN_LEFT)
1872 && (player.Current_Movement & PLAYER_LEAN_RIGHT))
1873 {
1874 }
1875 else
1876 {
1877 if (player.Current_Movement & PLAYER_LEAN_LEFT)
1878 {
1879 ChangeMoveAnim2 = alist[ANIM_LEAN_LEFT];
1880 //ChangeMA_Loop=0;
1881 }
1882
1883 if (player.Current_Movement & PLAYER_LEAN_RIGHT)
1884 {
1885 ChangeMoveAnim2 = alist[ANIM_LEAN_RIGHT];
1886 }
1887 }
1888 }
1889
1890 if ((ChangeMoveAnim2 == NULL)
1891 && (ause3->cur_anim)
1892 && ((ause3->cur_anim == alist[ANIM_LEAN_RIGHT])
1893 || (ause3->cur_anim == alist[ANIM_LEAN_LEFT]))
1894 )
1895 {
1896 AcquireLastAnim(io);
1897 ause3->cur_anim = NULL;
1898 }
1899
1900 if ((player.Current_Movement & PLAYER_CROUCH) && !(player.Last_Movement & PLAYER_CROUCH)
1901 && !player.levitate)
1902 {
1903 ChangeMoveAnim = alist[ANIM_CROUCH_START];
1904 ChangeMA_Loop = 0;
1905 }
1906 else if (!(player.Current_Movement & PLAYER_CROUCH) && (player.Last_Movement & PLAYER_CROUCH))
1907 {
1908 ChangeMoveAnim = alist[ANIM_CROUCH_END];
1909 ChangeMA_Loop = 0;
1910 }
1911 else if (player.Current_Movement & PLAYER_CROUCH)
1912 {
1913 if (ause0->cur_anim == alist[ANIM_CROUCH_START])
1914 {
1915 if (!(ause0->flags & EA_ANIMEND))
1916 {
1917 ChangeMoveAnim = alist[ANIM_CROUCH_START];
1918 ChangeMA_Loop = 0;
1919 }
1920 else
1921 {
1922 ChangeMoveAnim = alist[ANIM_CROUCH_WAIT];
1923 ChangeMA_Loop = 1;
1924 player.physics.cyl.height = player.crouchHeight();
1925 }
1926 }
1927 else
1928 {
1929 if ((ChangeMoveAnim == alist[ANIM_STRAFE_LEFT])
1930 || (ChangeMoveAnim == alist[ANIM_STRAFE_RUN_LEFT])
1931 || (ChangeMoveAnim == alist[ANIM_FIGHT_STRAFE_LEFT])
1932 )
1933 {
1934 ChangeMoveAnim = alist[ANIM_CROUCH_STRAFE_LEFT];
1935 ChangeMA_Loop = 1;
1936 }
1937 else if ((ChangeMoveAnim == alist[ANIM_STRAFE_RIGHT])
1938 || (ChangeMoveAnim == alist[ANIM_STRAFE_RUN_RIGHT])
1939 || (ChangeMoveAnim == alist[ANIM_FIGHT_STRAFE_RIGHT])
1940 )
1941 {
1942 ChangeMoveAnim = alist[ANIM_CROUCH_STRAFE_RIGHT];
1943 ChangeMA_Loop = 1;
1944 }
1945 else if ((ChangeMoveAnim == alist[ANIM_WALK])
1946 || (ChangeMoveAnim == alist[ANIM_RUN])
1947 || (ChangeMoveAnim == alist[ANIM_FIGHT_WALK_FORWARD])
1948 )
1949 {
1950 ChangeMoveAnim = alist[ANIM_CROUCH_WALK];
1951 ChangeMA_Loop = 1;
1952 }
1953 else if ((ChangeMoveAnim == alist[ANIM_WALK_BACKWARD])
1954 || (ChangeMoveAnim == alist[ANIM_FIGHT_WALK_BACKWARD])
1955 )
1956 {
1957 ChangeMoveAnim = alist[ANIM_CROUCH_WALK_BACKWARD];
1958 ChangeMA_Loop = 1;
1959 }
1960 else
1961 {
1962 ChangeMoveAnim = alist[ANIM_CROUCH_WAIT];
1963 ChangeMA_Loop = 1;
1964 }
1965 }
1966 }
1967
1968 if (ause0->cur_anim == alist[ANIM_CROUCH_END])
1969 {
1970 if (!(ause0->flags & EA_ANIMEND))
1971 goto nochanges;
1972 }
1973
1974 retry:
1975 ;
1976
1977 if (ARX_SPELLS_ExistAnyInstance(SPELL_FLYING_EYE))
1978 {
1979 FistParticles |= 1;
1980 }
1981 else FistParticles &= ~1;
1982
1983 if (FistParticles)
1984 {
1985 light = 1;
1986
1987 if (FistParticles & 1)
1988 {
1989 ChangeMoveAnim = alist[ANIM_MEDITATION];
1990 ChangeMA_Loop = 1;
1991 }
1992
1993 EERIE_3DOBJ * eobj = io->obj;
1994 long pouet = 2;
1995
1996 while (pouet)
1997 {
1998 long id;
1999
2000 if (pouet == 2)
2001 id = io->obj->fastaccess.primary_attach;
2002 else
2003 id = GetActionPointIdx(io->obj, "left_attach");
2004
2005 pouet--;
2006
2007 if(id != -1) {
2008
2009 if(special[pouet] == -1) {
2010 special[pouet] = GetFreeDynLight();
2011 }
2012 if(special[pouet] != -1) {
2013 EERIE_LIGHT * el = &DynLight[special[pouet]];
2014 el->intensity = 1.3f;
2015 el->exist = 1;
2016 el->fallend = 180.f;
2017 el->fallstart = 50.f;
2018 if(FistParticles & 2) {
2019 el->rgb = Color3f(1.f, 0.3f, 0.2f);
2020 } else {
2021 el->rgb = Color3f(0.7f, 0.3f, 1.f);
2022 }
2023 el->pos = eobj->vertexlist3[id].v;
2024 } else {
2025 LogWarning << "Maximum number of dynamic lights exceeded.";
2026 }
2027
2028 for(long kk = 0; kk < 2; kk++) {
2029
2030 PARTICLE_DEF * pd = createParticle();
2031 if(!pd) {
2032 break;
2033 }
2034
2035 pd->ov = eobj->vertexlist3[id].v + randomVec(-1.f, 1.f);
2036 pd->move = Vec3f(0.1f - 0.2f * rnd(), -2.2f * rnd(), 0.1f - 0.2f * rnd());
2037 pd->siz = 5.f;
2038 pd->tolive = Random::get(1500, 3500);
2039 pd->scale = Vec3f::repeat(0.2f);
2040 pd->tc = TC_smoke;
2041 pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING;
2042 pd->sourceionum = 0;
2043 pd->source = &eobj->vertexlist3[id].v;
2044 pd->fparam = 0.0000001f;
2045 if(FistParticles & 2) {
2046 pd->move.y *= 2.f;
2047 pd->rgb = Color3f(1.f - rnd() * .1f, .3f + rnd() * .1f, .2f - rnd() * .1f);
2048 } else {
2049 pd->rgb = Color3f(.7f - rnd() * .1f, .3f - rnd() * .1f, 1.f - rnd() * .1f);
2050 }
2051 }
2052 }
2053 }
2054
2055 goto makechanges;
2056 }
2057 else if (ARX_SPELLS_GetSpellOn(io, SPELL_LEVITATE) >= 0)
2058 {
2059 ChangeMoveAnim = alist[ANIM_LEVITATE];
2060 ChangeMA_Loop = 1;
2061 goto makechanges;
2062
2063 } else if(player.jumpphase != NotJumping) {
2064
2065 switch(player.jumpphase) {
2066
2067 case NotJumping: break;
2068
2069 case JumpStart: { // Anticipation
2070 FALLING_TIME = 0;
2071 player.jumpphase = JumpAscending;
2072 ChangeMoveAnim = alist[ANIM_JUMP_UP];
2073 player.jumpstarttime = (unsigned long)(arxtime);
2074 player.jumplastposition = -1.f;
2075 break;
2076 }
2077
2078 case JumpAscending: { // Moving up
2079 ChangeMoveAnim = alist[ANIM_JUMP_UP];
2080 if(player.jumplastposition >= 1.f) {
2081 player.jumpphase = JumpDescending;
2082 ChangeMoveAnim = alist[ANIM_JUMP_CYCLE];
2083 ARX_PLAYER_StartFall();
2084 }
2085 break;
2086 }
2087
2088 case JumpDescending: { // Post-synch
2089 LAST_JUMP_ENDTIME = (unsigned long)(arxtime);
2090 if((ause0->cur_anim == alist[ANIM_JUMP_END] && (ause0->flags & EA_ANIMEND))
2091 || player.onfirmground) {
2092 player.jumpphase = JumpEnd;
2093 ChangeMoveAnim = alist[ANIM_JUMP_END_PART2];
2094 } else {
2095 ChangeMoveAnim = alist[ANIM_JUMP_END];
2096 }
2097 break;
2098 }
2099
2100 case JumpEnd: { // Post-synch
2101 LAST_JUMP_ENDTIME = (unsigned long)(arxtime);
2102 if(ause0->cur_anim == alist[ANIM_JUMP_END_PART2]
2103 && (ause0->flags & EA_ANIMEND)) {
2104 AcquireLastAnim(io);
2105 player.jumpphase = NotJumping;
2106 goto retry;
2107 } else if(ause0->cur_anim == alist[ANIM_JUMP_END_PART2]
2108 && EEfabs(player.physics.velocity.x)
2109 + EEfabs(player.physics.velocity.z) > (4.f/TARGET_DT)
2110 && ause0->ctime > 1) {
2111 AcquireLastAnim(io);
2112 player.jumpphase = NotJumping;
2113 goto retry;
2114 } else {
2115 ChangeMoveAnim = alist[ANIM_JUMP_END_PART2];
2116 }
2117 break;
2118 }
2119
2120 }
2121
2122 if ((ChangeMoveAnim) && (ChangeMoveAnim != ause0->cur_anim))
2123 {
2124 AcquireLastAnim(io);
2125 ResetAnim(ause0);
2126 ause0->cur_anim = ChangeMoveAnim;
2127 ause0->flags = EA_STATICANIM;
2128
2129 if ((ChangeMoveAnim == alist[ANIM_U_TURN_LEFT])
2130 || (ChangeMoveAnim == alist[ANIM_U_TURN_RIGHT])
2131 || (ChangeMoveAnim == alist[ANIM_U_TURN_RIGHT_FIGHT])
2132 || (ChangeMoveAnim == alist[ANIM_U_TURN_LEFT_FIGHT]))
2133 ause0->flags |= EA_EXCONTROL;
2134 }
2135
2136 if ((ChangeMoveAnim2) && (ChangeMoveAnim2 != ause3->cur_anim))
2137 {
2138 AcquireLastAnim(io);
2139 ResetAnim(ause3);
2140 ause3->cur_anim = ChangeMoveAnim2;
2141 ause3->flags = EA_STATICANIM;
2142 }
2143 }
2144 else
2145 {
2146 makechanges:
2147 ;
2148
2149 if ((ChangeMoveAnim) && (ChangeMoveAnim != ause0->cur_anim))
2150 {
2151 AcquireLastAnim(io);
2152 ResetAnim(ause0);
2153 ause0->cur_anim = ChangeMoveAnim;
2154 ause0->flags = EA_STATICANIM;
2155
2156 if (ChangeMA_Loop) ause0->flags |= EA_LOOP;
2157
2158 if (ChangeMA_Stopend) ause0->flags |= EA_STOPEND;
2159
2160 if ((ChangeMoveAnim == alist[ANIM_U_TURN_LEFT])
2161 || (ChangeMoveAnim == alist[ANIM_U_TURN_RIGHT])
2162 || (ChangeMoveAnim == alist[ANIM_U_TURN_RIGHT_FIGHT])
2163 || (ChangeMoveAnim == alist[ANIM_U_TURN_LEFT_FIGHT]))
2164 ause0->flags |= EA_EXCONTROL;
2165 }
2166
2167 if ((ChangeMoveAnim2) && (ChangeMoveAnim2 != ause3->cur_anim))
2168 {
2169 AcquireLastAnim(io);
2170 ResetAnim(ause3);
2171 ause3->cur_anim = ChangeMoveAnim2;
2172 ause3->flags = EA_STATICANIM;
2173 }
2174 }
2175
2176 memcpy(&io->physics, &player.physics, sizeof(IO_PHYSICS));
2177 }
2178
2179 nochanges:
2180 ;
2181 player.Last_Movement = player.Current_Movement;
2182
2183 if (!light)
2184 {
2185 if (special[2] != -1)
2186 {
2187 DynLight[special[2]].exist = 0;
2188 special[2] = -1;
2189 }
2190
2191 if (special[1] != -1)
2192 {
2193 DynLight[special[1]].exist = 0;
2194 special[1] = -1;
2195 }
2196 }
2197 }
2198
2199 // Init Local Player Data
ARX_PLAYER_InitPlayer()2200 void ARX_PLAYER_InitPlayer() {
2201 player.Interface = INTER_MINIBOOK | INTER_MINIBACK | INTER_LIFE_MANA;
2202 player.physics.cyl.height = player.baseHeight();
2203 player.physics.cyl.radius = player.baseRadius();
2204 player.life = player.maxlife = player.Full_maxlife = 100.f;
2205 player.mana = player.maxmana = player.Full_maxmana = 100.f;
2206 player.falling = 0;
2207 player.rightIO = NULL;
2208 player.leftIO = NULL;
2209 player.equipsecondaryIO = NULL;
2210 player.equipshieldIO = NULL;
2211 player.gold = 0;
2212 player.bag = 1;
2213 player.doingmagic = 0;
2214 ARX_PLAYER_MakeFreshHero();
2215 }
2216
2217 // Forces player orientation to look at an IO
ForcePlayerLookAtIO(Entity * io)2218 void ForcePlayerLookAtIO(Entity * io) {
2219
2220 // Validity Check
2221 if (!io) return;
2222
2223 EERIE_CAMERA tcam;
2224 Vec3f target;
2225
2226 long id = entities.player()->obj->fastaccess.view_attach;
2227
2228 if(id != -1) {
2229 tcam.pos = entities.player()->obj->vertexlist3[id].v;
2230 } else {
2231 tcam.pos = player.pos;
2232 }
2233
2234 id = io->obj->fastaccess.view_attach;
2235
2236 if(id != -1) {
2237 target = io->obj->vertexlist3[id].v;
2238 }
2239 else
2240 {
2241 target = io->pos;
2242 }
2243
2244 // For the case of not already computed Vlist3... !
2245 if(fartherThan(target, io->pos, 400.f)) {
2246 target = io->pos;
2247 }
2248
2249 SetTargetCamera(&tcam, target.x, target.y, target.z);
2250 player.desiredangle.a = player.angle.a = MAKEANGLE(-tcam.angle.a);
2251 player.desiredangle.b = player.angle.b = MAKEANGLE(tcam.angle.b - 180.f);
2252 player.angle.g = 0;
2253 }
2254 extern float PLAYER_ARMS_FOCAL;
2255 extern long CURRENT_BASE_FOCAL;
2256 extern long TRAP_DETECT;
2257 extern long TRAP_SECRET;
2258
2259
2260 //*************************************************************************************
2261 // void ARX_PLAYER_Frame_Update()
2262 //-------------------------------------------------------------------------------------
2263 // FUNCTION/RESULT:
2264 // Updates Many player infos each frame...
2265 //*************************************************************************************
ARX_PLAYER_Frame_Update()2266 void ARX_PLAYER_Frame_Update()
2267 {
2268 if (ARX_SPELLS_GetSpellOn(entities.player(), SPELL_PARALYSE) >= 0)
2269 {
2270 PLAYER_PARALYSED = 1;
2271 }
2272 else
2273 {
2274 entities.player()->ioflags &= ~IO_FREEZESCRIPT;
2275 PLAYER_PARALYSED = 0;
2276 }
2277
2278 // Reset player moveto info
2279 moveto = player.pos;
2280
2281 // Reset current movement flags
2282 player.Current_Movement = 0;
2283
2284 // Updates player angles to desired angles
2285 player.angle.a = player.desiredangle.a;
2286 player.angle.b = player.desiredangle.b;
2287
2288 // Updates player Extra-Rotate Informations
2289 Entity * io;
2290 io = entities.player();
2291
2292 if ((io) && (io->_npcdata->ex_rotate))
2293 {
2294 float v = player.angle.a;
2295
2296 if (v > 160) v = -(360 - v);
2297
2298 if (player.Interface & INTER_COMBATMODE)
2299 {
2300 if (ARX_EQUIPMENT_GetPlayerWeaponType() == WEAPON_BOW)
2301 {
2302 io->_npcdata->ex_rotate->group_rotate[0].a = 0; //head
2303 io->_npcdata->ex_rotate->group_rotate[1].a = 0; //neck
2304 io->_npcdata->ex_rotate->group_rotate[2].a = 0; //chest
2305 io->_npcdata->ex_rotate->group_rotate[3].a = v; //belt
2306 }
2307 else
2308 {
2309 v *= ( 1.0f / 10 );
2310 io->_npcdata->ex_rotate->group_rotate[0].a = v; //head
2311 io->_npcdata->ex_rotate->group_rotate[1].a = v; //neck
2312 io->_npcdata->ex_rotate->group_rotate[2].a = v * 4; //chest
2313 io->_npcdata->ex_rotate->group_rotate[3].a = v * 4; //belt
2314 }
2315
2316 }
2317 else
2318 {
2319 v *= ( 1.0f / 4 );
2320 io->_npcdata->ex_rotate->group_rotate[0].a = v; //head
2321 io->_npcdata->ex_rotate->group_rotate[1].a = v; //neck
2322 io->_npcdata->ex_rotate->group_rotate[2].a = v; //chest
2323 io->_npcdata->ex_rotate->group_rotate[3].a = v; //belt*/
2324 }
2325
2326 if ((player.Interface & INTER_COMBATMODE) || (player.doingmagic == 2))
2327 io->_npcdata->ex_rotate->flags &= ~EXTRA_ROTATE_REALISTIC;
2328 }
2329
2330 // Changes player ARMS focal depending on alpha angle.
2331 if (player.angle.a > 180)
2332 PLAYER_ARMS_FOCAL = (float)CURRENT_BASE_FOCAL - 80.f;
2333 else
2334 PLAYER_ARMS_FOCAL = (float)CURRENT_BASE_FOCAL - 80.f + player.angle.a;
2335
2336 PLAYER_ARMS_FOCAL = static_cast<float>(CURRENT_BASE_FOCAL);
2337
2338 ARX_PLAYER_ComputePlayerFullStats();
2339
2340 TRAP_DETECT = checked_range_cast<long>(player.Full_Skill_Mecanism);
2341 TRAP_SECRET = checked_range_cast<long>(player.Full_Skill_Intuition);
2342
2343 if (ARX_SPELLS_GetSpellOn(entities.player(), SPELL_DETECT_TRAP) >= 0)
2344 TRAP_DETECT = 100;
2345
2346 ModeLight |= MODE_DEPTHCUEING;
2347
2348 ARX_PLAYER_ManageTorch();
2349 }
2350
2351 // Emit player step noise
ARX_PLAYER_MakeStepNoise()2352 static void ARX_PLAYER_MakeStepNoise() {
2353
2354 if(ARX_SPELLS_GetSpellOn(entities.player(), SPELL_LEVITATE) >= 0) {
2355 return;
2356 }
2357
2358 if(USE_PLAYERCOLLISIONS) {
2359
2360 float volume = ARX_NPC_AUDIBLE_VOLUME_DEFAULT;
2361 float factor = ARX_NPC_AUDIBLE_FACTOR_DEFAULT;
2362
2363 if(player.Current_Movement & PLAYER_MOVE_STEALTH) {
2364 float skill_stealth;
2365 skill_stealth = player.Full_Skill_Stealth / ARX_PLAYER_SKILL_STEALTH_MAX;
2366 volume -= ARX_NPC_AUDIBLE_VOLUME_RANGE * skill_stealth;
2367 factor += ARX_NPC_AUDIBLE_FACTOR_RANGE * skill_stealth;
2368 }
2369
2370 Vec3f pos = player.basePosition();
2371 ARX_NPC_NeedStepSound(entities.player(), &pos, volume, factor);
2372 }
2373
2374 while(currentdistance >= STEP_DISTANCE) {
2375 currentdistance -= STEP_DISTANCE;
2376 }
2377 }
2378
2379 extern bool bGCroucheToggle;
2380 extern float MAX_ALLOWED_PER_SECOND;
2381
2382 static long LAST_FIRM_GROUND = 1;
2383 static long TRUE_FIRM_GROUND = 1;
2384 float lastposy = -9999999.f;
2385 unsigned long REQUEST_JUMP = 0;
2386 extern float GLOBAL_SLOWDOWN;
2387 extern float Original_framedelay;
2388
2389 unsigned long LAST_JUMP_ENDTIME = 0;
2390
Valid_Jump_Pos()2391 bool Valid_Jump_Pos() {
2392
2393 if(LAST_ON_PLATFORM || player.climbing) {
2394 return true;
2395 }
2396
2397 EERIE_CYLINDER tmpp;
2398 tmpp.height = player.physics.cyl.height;
2399 tmpp.origin = player.basePosition();
2400 tmpp.radius = player.physics.cyl.radius * 0.85f;
2401 float tmp = CheckAnythingInCylinder(&tmpp, entities.player(),
2402 CFLAG_PLAYER | CFLAG_JUST_TEST);
2403 if(tmp <= 20.f) {
2404 return true;
2405 }
2406
2407 long hum = 0;
2408 for(float vv = 0; vv < 360.f; vv += 20.f) {
2409 tmpp.origin = player.basePosition();
2410 tmpp.origin += Vec3f(-EEsin(radians(vv)) * 20.f, 0.f, EEcos(radians(vv)) * 20.f);
2411 tmpp.radius = player.physics.cyl.radius;
2412 float anything = CheckAnythingInCylinder(&tmpp, entities.player(), CFLAG_JUST_TEST);
2413 if(anything > 10) {
2414 hum = 1;
2415 break;
2416 }
2417 }
2418 if(!hum) {
2419 return true;
2420 }
2421
2422 if(COLLIDED_CLIMB_POLY) {
2423 player.climbing = 1;
2424 return true;
2425 }
2426
2427 return (tmp <= 50.f);
2428 }
2429
2430 void PlayerMovementIterate(float DelatTime);
2431
ARX_PLAYER_Manage_Movement()2432 void ARX_PLAYER_Manage_Movement() {
2433
2434 // Is our player able to move ?
2435 if ((CINEMASCOPE)
2436 || (BLOCK_PLAYER_CONTROLS)
2437 || (entities.player() == NULL))
2438 return;
2439
2440 float speedfactor;
2441 // Compute current player speedfactor
2442 speedfactor = entities.player()->basespeed + entities.player()->speed_modif;
2443
2444 if (speedfactor < 0) speedfactor = 0;
2445
2446 if (cur_mr == 3) speedfactor += 0.5f;
2447
2448 if (cur_rf == 3) speedfactor += 1.5f;
2449
2450 // Compute time things
2451 const float FIXED_TIMESTEP = 25.f;
2452 const float MAX_FRAME_TIME = 200.f;
2453
2454 static float StoredTime = 0;
2455
2456 float DeltaTime = std::min(Original_framedelay, MAX_FRAME_TIME);
2457 DeltaTime = StoredTime + DeltaTime * speedfactor;
2458
2459 if(EDITMODE) {
2460 DeltaTime = FIXED_TIMESTEP;
2461 }
2462
2463 if(player.jumpphase != NotJumping) {
2464 while(DeltaTime > FIXED_TIMESTEP) {
2465 /*
2466 * TODO: should be PlayerMovementIterate(FIXED_TIMESTEP);
2467 * However, jump forward movement is only applied the the first
2468 * iteration, so we need this to not completely break the jump
2469 * at lower framerates.
2470 * Should only cause minor differences at higher framerates.
2471 * Fix this once PlayerMovementIterate has been cleaned up!
2472 */
2473 PlayerMovementIterate(DeltaTime);
2474 DeltaTime -= FIXED_TIMESTEP;
2475 }
2476 } else {
2477 PlayerMovementIterate(DeltaTime);
2478 DeltaTime = 0;
2479 }
2480
2481 StoredTime = DeltaTime;
2482 }
2483
PlayerMovementIterate(float DeltaTime)2484 void PlayerMovementIterate(float DeltaTime) {
2485
2486 // A jump is requested so let's go !
2487 if(REQUEST_JUMP) {
2488
2489 if((player.Current_Movement & PLAYER_CROUCH)
2490 || player.physics.cyl.height > player.baseHeight()) {
2491 float old = player.physics.cyl.height;
2492 player.physics.cyl.height = player.baseHeight();
2493 player.physics.cyl.origin = player.basePosition();
2494 float anything = CheckAnythingInCylinder(&player.physics.cyl, entities.player(),
2495 CFLAG_JUST_TEST);
2496 if(anything < 0.f) {
2497 player.Current_Movement |= PLAYER_CROUCH;
2498 player.physics.cyl.height = old;
2499 REQUEST_JUMP = 0;
2500 } else {
2501 bGCroucheToggle = false;
2502 player.Current_Movement &= ~PLAYER_CROUCH;
2503 player.physics.cyl.height = player.baseHeight();
2504 }
2505 }
2506
2507 if(!Valid_Jump_Pos()) {
2508 REQUEST_JUMP = 0;
2509 }
2510
2511 if(REQUEST_JUMP) {
2512 float t = (float)float(arxtime) - (float)REQUEST_JUMP;
2513 if(t >= 0.f && t <= 350.f) {
2514 REQUEST_JUMP = 0;
2515 ARX_NPC_SpawnAudibleSound(&player.pos, entities.player());
2516 ARX_SPEECH_Launch_No_Unicode_Seek("player_jump", entities.player());
2517 player.onfirmground = 0;
2518 player.jumpphase = JumpStart;
2519 }
2520 }
2521
2522 }
2523
2524 if(entities.player()->_npcdata->climb_count != 0.f && FrameDiff > 0) {
2525 entities.player()->_npcdata->climb_count -= MAX_ALLOWED_PER_SECOND * FrameDiff * 0.1f;
2526 if(entities.player()->_npcdata->climb_count < 0) {
2527 entities.player()->_npcdata->climb_count = 0.f;
2528 }
2529 }
2530
2531 float d = 0;
2532
2533 if(!EDITMODE && USE_PLAYERCOLLISIONS) {
2534
2535 CollisionFlags levitate = 0;
2536 if(player.climbing) {
2537 levitate = CFLAG_LEVITATE;
2538 }
2539
2540 if(player.levitate) {
2541
2542 if(player.physics.cyl.height != player.levitateHeight()) {
2543 float old = player.physics.cyl.height;
2544 player.physics.cyl.height = player.levitateHeight();
2545 player.physics.cyl.origin = player.basePosition();
2546 float anything = CheckAnythingInCylinder(&player.physics.cyl, entities.player());
2547 if(anything < 0.f) {
2548 player.physics.cyl.height = old;
2549 long num = ARX_SPELLS_GetSpellOn(entities.player(), SPELL_LEVITATE);
2550 if(num != -1) {
2551 spells[num].tolive = 0;
2552 }
2553 }
2554 }
2555
2556 if(player.physics.cyl.height == player.levitateHeight()) {
2557 levitate = CFLAG_LEVITATE;
2558 player.climbing = 0;
2559 bGCroucheToggle = false;
2560 player.Current_Movement &= ~PLAYER_CROUCH;
2561 }
2562
2563 } else if(player.physics.cyl.height == player.levitateHeight()) {
2564 player.physics.cyl.height = player.baseHeight();
2565 }
2566
2567 if(player.jumpphase != JumpAscending && !levitate) {
2568 player.physics.cyl.origin = player.basePosition();
2569 }
2570
2571 if(EEfabs(lastposy - player.pos.y) < DeltaTime * 0.1f) {
2572 TRUE_FIRM_GROUND = 1;
2573 } else {
2574 TRUE_FIRM_GROUND = 0;
2575 }
2576
2577 lastposy = player.pos.y;
2578 float anything;
2579 EERIE_CYLINDER testcyl;
2580 memcpy(&testcyl, &player.physics.cyl, sizeof(EERIE_CYLINDER));
2581 testcyl.origin.y += 3.f;
2582 ON_PLATFORM = 0;
2583 anything = CheckAnythingInCylinder(&testcyl, entities.player(), 0);
2584 LAST_ON_PLATFORM = ON_PLATFORM;
2585
2586 if(player.jumpphase != JumpAscending) {
2587 if(anything >= 0.f) {
2588 TRUE_FIRM_GROUND = 0;
2589 } else {
2590 TRUE_FIRM_GROUND = 1;
2591 testcyl.radius -= 30.f;
2592 testcyl.origin.y -= 10.f;
2593 anything = CheckAnythingInCylinder(&testcyl, entities.player(), 0);
2594 }
2595 } else {
2596 TRUE_FIRM_GROUND = 0;
2597 LAST_ON_PLATFORM = 0;
2598 }
2599
2600 EERIE_CYLINDER cyl;
2601 cyl.origin = player.basePosition() + Vec3f(0.f, 1.f, 0.f);
2602 cyl.radius = player.physics.cyl.radius;
2603 cyl.height = player.physics.cyl.height;
2604 float anything2 = CheckAnythingInCylinder(&cyl, entities.player(), CFLAG_JUST_TEST | CFLAG_PLAYER); //-cyl->origin.y;
2605
2606 if(anything2 > -5 && player.physics.velocity.y > (15.f/TARGET_DT) && !LAST_ON_PLATFORM
2607 && !TRUE_FIRM_GROUND && player.jumpphase == NotJumping && !player.levitate
2608 && anything > 80.f) {
2609 player.jumpphase = JumpDescending;
2610 if(!player.falling) {
2611 player.falling = 1;
2612 ARX_PLAYER_StartFall();
2613 }
2614 } else if(!player.falling) {
2615 FALLING_TIME = 0;
2616 }
2617
2618 if(player.jumpphase != NotJumping && player.levitate) {
2619 player.jumpphase = NotJumping;
2620 player.falling = 0;
2621 Falling_Height = player.pos.y;
2622 FALLING_TIME = 0;
2623 }
2624
2625 if(!LAST_FIRM_GROUND && TRUE_FIRM_GROUND) {
2626 player.jumpphase = NotJumping;
2627 if(FALLING_TIME > 0 && player.falling) {
2628 player.physics.velocity.x = 0.f;
2629 player.physics.velocity.z = 0.f;
2630 player.physics.forces.x = 0.f;
2631 player.physics.forces.z = 0.f;
2632 player.falling = 0;
2633 float fh = player.pos.y - Falling_Height;
2634 if(fh > 400.f) {
2635 float dmg = (fh - 400.f) * (1.0f / 15);
2636 if(dmg > 0.f) {
2637 Falling_Height = player.pos.y;
2638 FALLING_TIME = 0;
2639 ARX_DAMAGES_DamagePlayer(dmg, 0, -1);
2640 ARX_DAMAGES_DamagePlayerEquipment(dmg);
2641 }
2642 }
2643 }
2644 }
2645
2646 LAST_FIRM_GROUND = TRUE_FIRM_GROUND;
2647 player.onfirmground = TRUE_FIRM_GROUND;
2648 if(player.onfirmground && !player.falling) {
2649 FALLING_TIME = 0;
2650 }
2651
2652 // Apply player impulse force
2653
2654 float jump_mul = 1.f;
2655 if(float(arxtime) - LAST_JUMP_ENDTIME < 600) {
2656 jump_mul = 0.5f;
2657 if(float(arxtime) - LAST_JUMP_ENDTIME >= 300) {
2658 jump_mul += (float)(LAST_JUMP_ENDTIME + 300 - float(arxtime)) * (1.f / 300);
2659 if(jump_mul > 1.f) {
2660 jump_mul = 1.f;
2661 }
2662 }
2663 }
2664
2665 Vec3f impulse = moveto - player.pos;
2666 if(impulse != Vec3f::ZERO) {
2667
2668 float scale = 1.25f / 1000;
2669 if(entities.player()->animlayer[0].cur_anim) {
2670 if(player.jumpphase != NotJumping) {
2671 if(player.Current_Movement & PLAYER_MOVE_WALK_BACKWARD) {
2672 scale = 0.8f / 1000;
2673 } else if(player.Current_Movement & PLAYER_MOVE_WALK_FORWARD) {
2674 scale = 7.9f / 1000;
2675 } else if(player.Current_Movement & PLAYER_MOVE_STRAFE_LEFT) {
2676 scale = 2.6f / 1000;
2677 } else if(player.Current_Movement & PLAYER_MOVE_STRAFE_RIGHT) {
2678 scale = 2.6f / 1000;
2679 } else {
2680 scale = 0.2f / 1000;
2681 }
2682 } else if(levitate && !player.climbing) {
2683 scale = 0.875f / 1000;
2684 } else {
2685 Vec3f mv;
2686 short idx = entities.player()->animlayer[0].altidx_cur;
2687 GetAnimTotalTranslate(entities.player()->animlayer[0].cur_anim, idx, &mv);
2688 float time = entities.player()->animlayer[0].cur_anim->anims[idx]->anim_time;
2689 scale = mv.length() / time * 0.0125f;
2690 }
2691 }
2692
2693 impulse *= scale / impulse.length() * jump_mul;
2694 }
2695
2696 if(player.jumpphase != NotJumping) {
2697 // No Vertical Interpolation
2698 entities.player()->_npcdata->vvpos = -99999.f;
2699 if(player.jumpphase == JumpAscending) {
2700 moveto.y = player.pos.y;
2701 player.physics.velocity.y = 0;
2702 }
2703 }
2704
2705 if(player.climbing) {
2706 player.physics.velocity.x = 0.f;
2707 player.physics.velocity.y *= 0.5f;
2708 player.physics.velocity.z = 0.f;
2709 if(player.Current_Movement & PLAYER_MOVE_WALK_FORWARD) {
2710 moveto.x = player.pos.x;
2711 moveto.z = player.pos.z;
2712 }
2713 if(player.Current_Movement & PLAYER_MOVE_WALK_BACKWARD) {
2714 impulse.x = 0;
2715 impulse.z = 0;
2716 moveto.x = player.pos.x;
2717 moveto.z = player.pos.z;
2718 }
2719 }
2720
2721 player.physics.forces += impulse;
2722
2723 // Apply Gravity force if not LEVITATING or JUMPING
2724 if(!levitate && player.jumpphase != JumpAscending && !LAST_ON_PLATFORM) {
2725
2726 player.physics.forces.y += ((player.falling) ? JUMP_GRAVITY : WORLD_GRAVITY) / TARGET_DT;
2727
2728 // Check for LAVA Damage !!!
2729 float epcentery;
2730 EERIEPOLY * ep = CheckInPoly(player.pos.x, player.pos.y + 150.f, player.pos.z,
2731 &epcentery);
2732 if(ep) {
2733 if((ep->type & POLY_LAVA)
2734 && EEfabs(epcentery - (player.pos.y - player.baseHeight())) < 30) {
2735 float mul = 1.f - (EEfabs(epcentery - (player.pos.y - player.baseHeight()))
2736 * (1.0f / 30));
2737 const float LAVA_DAMAGE = 10.f;
2738 float damages = LAVA_DAMAGE * FrameDiff * 0.01f * mul;
2739 damages = ARX_SPELLS_ApplyFireProtection(entities.player(), damages);
2740 ARX_DAMAGES_DamagePlayer(damages, DAMAGE_TYPE_FIRE, 0);
2741 ARX_DAMAGES_DamagePlayerEquipment(damages);
2742 Vec3f pos = player.basePosition();
2743 ARX_PARTICLES_Spawn_Lava_Burn(&pos, entities.player());
2744 }
2745 }
2746
2747 }
2748
2749 // Apply velocity damping (natural velocity attenuation, stands for friction)
2750 float dampen = 1.f - (0.009f * DeltaTime);
2751 if(dampen < 0.001f) {
2752 dampen = 0.f;
2753 }
2754 player.physics.velocity.x *= dampen;
2755 player.physics.velocity.z *= dampen;
2756 if(EEfabs(player.physics.velocity.x) < 0.001f) {
2757 player.physics.velocity.x = 0;
2758 }
2759 if(EEfabs(player.physics.velocity.z) < 0.001f) {
2760 player.physics.velocity.z = 0;
2761 }
2762
2763 // Apply attraction
2764 Vec3f attraction;
2765 ARX_SPECIAL_ATTRACTORS_ComputeForIO(*entities.player(), attraction);
2766 player.physics.forces += attraction / TARGET_DT;
2767
2768 // Apply push player force
2769 player.physics.forces += PUSH_PLAYER_FORCE / TARGET_DT;
2770 PUSH_PLAYER_FORCE = Vec3f::ZERO;
2771
2772 // Apply forces to velocity
2773 player.physics.velocity += player.physics.forces * DeltaTime;
2774
2775 // Apply climbing velocity
2776 if(player.climbing) {
2777 if(player.Current_Movement & PLAYER_MOVE_WALK_FORWARD) {
2778 player.physics.velocity.y = -0.2f;
2779 }
2780 if(player.Current_Movement & PLAYER_MOVE_WALK_BACKWARD) {
2781 player.physics.velocity.y = 0.2f;
2782 }
2783 }
2784
2785 // Removes y velocity if on firm ground...
2786 if(player.onfirmground == 1 && !player.climbing) {
2787 player.physics.velocity.y = 0.f;
2788 }
2789
2790 float posy;
2791 EERIEPOLY * ep = CheckInPolyPrecis(player.pos.x, player.pos.y, player.pos.z, &posy);
2792 if(ep == NULL) {
2793 player.physics.velocity.y = 0;
2794 } else if(!player.climbing && player.pos.y >= posy) {
2795 player.physics.velocity.y = 0;
2796 }
2797
2798 // Reset forces
2799 player.physics.forces = Vec3f::ZERO;
2800
2801 // Check if player is already on firm ground AND not moving
2802 if(EEfabs(player.physics.velocity.x) < 0.001f
2803 && EEfabs(player.physics.velocity.z) < 0.001f
2804 && player.onfirmground == 1 && player.jumpphase == NotJumping) {
2805 moveto = player.pos;
2806 goto lasuite;
2807 } else {
2808
2809 // Need to apply some physics/collision tests
2810 player.physics.cyl.origin = player.basePosition();
2811 player.physics.startpos = player.physics.cyl.origin;
2812 player.physics.targetpos = player.physics.startpos + player.physics.velocity * DeltaTime;
2813
2814 // Jump impulse
2815 if(player.jumpphase == JumpAscending) {
2816
2817 if(player.jumplastposition == -1.f) {
2818 player.jumplastposition = 0;
2819 player.jumpstarttime = (unsigned long)(arxtime);
2820 }
2821
2822 const float jump_up_time = 200.f;
2823 const float jump_up_height = 130.f;
2824 long timee = (long)arxtime;
2825 float offset_time = (float)timee - (float)player.jumpstarttime;
2826 float position = clamp(offset_time / jump_up_time, 0.f, 1.f);
2827
2828 float p = (position - player.jumplastposition) * jump_up_height;
2829 player.physics.targetpos.y -= p;
2830 player.jumplastposition = position;
2831 levitate = 0;
2832 }
2833
2834 bool test;
2835 float PLAYER_CYLINDER_STEP = 40.f;
2836 if(player.climbing) {
2837
2838 test = ARX_COLLISION_Move_Cylinder(&player.physics, entities.player(),
2839 PLAYER_CYLINDER_STEP,
2840 CFLAG_EASY_SLIDING | CFLAG_CLIMBING
2841 | CFLAG_PLAYER);
2842
2843 if(!COLLIDED_CLIMB_POLY) {
2844 player.climbing = 0;
2845 }
2846
2847 } else {
2848
2849 test = ARX_COLLISION_Move_Cylinder(&player.physics, entities.player(),
2850 PLAYER_CYLINDER_STEP,
2851 levitate | CFLAG_EASY_SLIDING | CFLAG_PLAYER);
2852
2853 if(!test && !LAST_FIRM_GROUND && !TRUE_FIRM_GROUND) {
2854 player.physics.velocity.x = 0.f;
2855 player.physics.velocity.z = 0.f;
2856 player.physics.forces.x = 0.f;
2857 player.physics.forces.z = 0.f;
2858 if(FALLING_TIME > 0 && player.falling) {
2859 float fh = player.pos.y - Falling_Height;
2860 if(fh > 400.f) {
2861 float dmg = (fh - 400.f) * (1.f / 15);
2862 if(dmg > 0.f) {
2863 Falling_Height = (player.pos.y + Falling_Height * 2) * (1.f / 3);
2864 ARX_DAMAGES_DamagePlayer(dmg, 0, -1);
2865 ARX_DAMAGES_DamagePlayerEquipment(dmg);
2866 }
2867 }
2868 }
2869 }
2870
2871 if(!test && player.jumpphase != NotJumping) {
2872 player.physics.startpos.x = player.physics.cyl.origin.x = player.pos.x;
2873 player.physics.startpos.z = player.physics.cyl.origin.z = player.pos.z;
2874 player.physics.targetpos.x = player.physics.startpos.x;
2875 player.physics.targetpos.z = player.physics.startpos.z;
2876 if(player.physics.targetpos.y != player.physics.startpos.y) {
2877 test = ARX_COLLISION_Move_Cylinder(&player.physics, entities.player(),
2878 PLAYER_CYLINDER_STEP,
2879 levitate | CFLAG_EASY_SLIDING
2880 | CFLAG_PLAYER);
2881 entities.player()->_npcdata->vvpos = -99999.f;
2882 }
2883 }
2884 }
2885
2886 if(COLLIDED_CLIMB_POLY) {
2887 player.climbing = 1;
2888 }
2889
2890 if(player.climbing) {
2891
2892 if(player.Current_Movement && player.Current_Movement != PLAYER_ROTATE
2893 && !(player.Current_Movement & PLAYER_MOVE_WALK_FORWARD)
2894 && !(player.Current_Movement & PLAYER_MOVE_WALK_BACKWARD)) {
2895 player.climbing = 0;
2896 }
2897
2898 if((player.Current_Movement & PLAYER_MOVE_WALK_BACKWARD) && !test) {
2899 player.climbing = 0;
2900 }
2901
2902 if(player.climbing) {
2903 player.jumpphase = NotJumping;
2904 player.falling = 0;
2905 FALLING_TIME = 0;
2906 Falling_Height = player.pos.y;
2907 }
2908 }
2909
2910 if(player.jumpphase == JumpAscending) {
2911 player.climbing = 0;
2912 }
2913
2914 moveto = player.physics.cyl.origin + player.baseOffset();
2915 d = dist(player.pos, moveto);
2916 }
2917
2918 } else {
2919
2920 if(!EDITMODE) {
2921 Vec3f vect = moveto - player.pos;
2922 float divv = vect.length();
2923 if(divv > 0.f) {
2924 float mul = (float)FrameDiff * 0.001f * 200.f;
2925 divv = mul / divv;
2926 vect *= divv;
2927 moveto = player.pos + vect;
2928 }
2929 }
2930
2931 player.onfirmground = 0;
2932 }
2933
2934 if(player.pos == moveto) {
2935 d = 0.f;
2936 }
2937
2938 // Emit Stepsound
2939 if(USE_PLAYERCOLLISIONS && !EDITMODE) {
2940 if(player.Current_Movement & PLAYER_CROUCH) {
2941 d *= 2.f;
2942 }
2943 currentdistance += d;
2944 if(player.jumpphase == NotJumping && !player.falling
2945 && currentdistance >= STEP_DISTANCE) {
2946 ARX_PLAYER_MakeStepNoise();
2947 }
2948 }
2949
2950 // Finally update player pos !
2951 player.pos = moveto;
2952
2953 lasuite:
2954 ;
2955
2956 // Get Player position color
2957 float grnd_color = GetColorz(player.pos.x, player.pos.y + 90, player.pos.z) - 15.f;
2958 if(CURRENT_PLAYER_COLOR < grnd_color) {
2959 CURRENT_PLAYER_COLOR += FrameDiff * (1.0f / 8);
2960 CURRENT_PLAYER_COLOR = std::min(CURRENT_PLAYER_COLOR, grnd_color);
2961 }
2962 if(CURRENT_PLAYER_COLOR > grnd_color) {
2963 CURRENT_PLAYER_COLOR -= FrameDiff * (1.0f / 4);
2964 CURRENT_PLAYER_COLOR = std::max(CURRENT_PLAYER_COLOR, grnd_color);
2965 }
2966
2967 if (InventoryDir != 0)
2968 {
2969 if ((player.Interface & INTER_COMBATMODE) || (player.doingmagic >= 2) || (InventoryDir == -1))
2970 {
2971 if (InventoryX > -160)
2972 InventoryX -= INTERFACE_RATIO(FrameDiff * ( 1.0f / 3 ));
2973 }
2974 else
2975 {
2976 if (InventoryX < 0)
2977 InventoryX += InventoryDir * INTERFACE_RATIO(FrameDiff * ( 1.0f / 3 ));
2978 }
2979
2980 if (InventoryX <= -160)
2981 {
2982 InventoryX = -160;
2983 InventoryDir = 0;
2984
2985 if (player.Interface & INTER_STEAL || ioSteal)
2986 {
2987 SendIOScriptEvent(ioSteal, SM_STEAL, "off");
2988 player.Interface &= ~INTER_STEAL;
2989 ioSteal = NULL;
2990 }
2991
2992 SecondaryInventory = NULL;
2993 TSecondaryInventory = NULL;
2994 InventoryDir = 0;
2995 }
2996 else if (InventoryX >= 0)
2997 {
2998 InventoryX = 0;
2999 InventoryDir = 0;
3000 }
3001 }
3002 }
3003 //******************************************************************************
3004 // Manage Player Death Visual
3005 //******************************************************************************
ARX_PLAYER_Manage_Death()3006 void ARX_PLAYER_Manage_Death()
3007 {
3008 PLAYER_PARALYSED = 0;
3009 float ratio = (float)(DeadTime - 2000) * ( 1.0f / 5000 );
3010
3011 if (ratio >= 1.f) ratio = 1.f;
3012
3013 if (ratio == 1.f)
3014 {
3015 ARX_MENU_Launch();
3016 DeadTime = 0;
3017 }
3018
3019 {
3020 GRenderer->SetRenderState(Renderer::AlphaBlending, true);
3021 GRenderer->SetBlendFunc(Renderer::BlendZero, Renderer::BlendInvSrcColor);
3022 EERIEDrawBitmap( 0.f, 0.f, static_cast<float>(DANAESIZX), static_cast<float>(DANAESIZY), 0.000091f, NULL, Color::gray(ratio));
3023
3024 }
3025 }
3026 //******************************************************************************
3027 // Specific for color checks
3028 //******************************************************************************
GetPlayerStealth()3029 float GetPlayerStealth()
3030 {
3031 return 15 + player.Full_Skill_Stealth * ( 1.0f / 10 );
3032 }
3033
3034 // Teleport player to any poly...
ARX_PLAYER_GotoAnyPoly()3035 void ARX_PLAYER_GotoAnyPoly() {
3036 for(long j = 0; j < ACTIVEBKG->Zsize; j++) {
3037 for(long i = 0; i < ACTIVEBKG->Xsize; i++) {
3038 EERIE_BKG_INFO * eg = &ACTIVEBKG->Backg[i + j * ACTIVEBKG->Xsize];
3039 if(eg->nbpoly) {
3040 player.pos = moveto = eg->polydata[0].center + player.baseOffset();
3041 }
3042 }
3043 }
3044 }
3045
3046 // Force Player to standard stance... (Need some improvements...)
ARX_PLAYER_PutPlayerInNormalStance(long val)3047 void ARX_PLAYER_PutPlayerInNormalStance(long val) {
3048
3049 if(player.Current_Movement & PLAYER_CROUCH) {
3050 player.Current_Movement &= ~PLAYER_CROUCH;
3051 }
3052
3053 player.Current_Movement = 0;
3054 ARX_PLAYER_RectifyPosition();
3055
3056 if(player.jumpphase != NotJumping || player.falling) {
3057 player.physics.cyl.origin = player.basePosition();
3058 IO_PHYSICS phys;
3059 memcpy(&phys, &player.physics, sizeof(IO_PHYSICS));
3060 AttemptValidCylinderPos(&phys.cyl, entities.player(), CFLAG_RETURN_HEIGHT);
3061 player.pos.y = phys.cyl.origin.y + player.baseHeight();
3062 player.jumpphase = NotJumping;
3063 player.falling = 0;
3064 }
3065
3066 if(player.Interface & INTER_COMBATMODE) {
3067 player.Interface &= ~INTER_COMBATMODE;
3068 ARX_EQUIPMENT_LaunchPlayerUnReadyWeapon();
3069 }
3070
3071 ARX_SOUND_Stop(SND_MAGIC_DRAW);
3072
3073 if(!val) {
3074 for(size_t i = 0; i < MAX_SPELLS; i++) {
3075 if(spells[i].exist && (spells[i].caster == 0 || spells[i].target == 0)) {
3076 switch(spells[i].type) {
3077 case SPELL_MAGIC_SIGHT:
3078 case SPELL_LEVITATE:
3079 case SPELL_SPEED:
3080 case SPELL_FLYING_EYE:
3081 spells[i].tolive = 0;
3082 break;
3083 default: break;
3084 }
3085 }
3086 }
3087 }
3088 }
3089
3090 // Add gold to player purse
ARX_PLAYER_AddGold(long _lValue)3091 void ARX_PLAYER_AddGold(long _lValue) {
3092 player.gold += _lValue;
3093 bGoldHalo = true;
3094 ulGoldHaloTime = 0;
3095 }
3096
ARX_PLAYER_AddGold(Entity * gold)3097 void ARX_PLAYER_AddGold(Entity * gold) {
3098
3099 arx_assert(gold->ioflags & IO_GOLD);
3100
3101 ARX_PLAYER_AddGold(gold->_itemdata->price * max((short)1, gold->_itemdata->count));
3102
3103 ARX_SOUND_PlayInterface(SND_GOLD);
3104
3105 gold->gameFlags &= ~GFLAG_ISINTREATZONE;
3106
3107 gold->destroy();
3108 }
3109
ARX_PLAYER_Start_New_Quest()3110 void ARX_PLAYER_Start_New_Quest() {
3111
3112 SKIN_MOD = 0;
3113 QUICK_MOD = 0;
3114 EERIE_PATHFINDER_Clear();
3115 EERIE_PATHFINDER_Release();
3116 ARX_PLAYER_MakeFreshHero();
3117 CURRENT_TORCH = NULL;
3118 entities.clear();
3119 SecondaryInventory = NULL;
3120 TSecondaryInventory = NULL;
3121 ARX_EQUIPMENT_UnEquipAllPlayer();
3122
3123 ARX_Changelevel_CurGame_Clear();
3124
3125 entities.player()->halo.flags = 0;
3126 }
3127
3128 //-----------------------------------------------------------------------------
ARX_PLAYER_AddBag()3129 void ARX_PLAYER_AddBag()
3130 {
3131 ++player.bag;
3132
3133 if (player.bag > 3)
3134 player.bag = 3;
3135 }
3136
3137 //-----------------------------------------------------------------------------
ARX_PLAYER_CanStealItem(Entity * _io)3138 bool ARX_PLAYER_CanStealItem(Entity * _io)
3139 {
3140 if (_io->_itemdata->stealvalue > 0)
3141 if ((player.Full_Skill_Stealth >= _io->_itemdata->stealvalue)
3142 && (_io->_itemdata->stealvalue < 100.f))
3143 {
3144 return true;
3145 }
3146
3147 return false;
3148 }
ARX_PLAYER_Rune_Add_All()3149 void ARX_PLAYER_Rune_Add_All()
3150 {
3151 ARX_Player_Rune_Add(FLAG_AAM);
3152 ARX_Player_Rune_Add(FLAG_CETRIUS);
3153 ARX_Player_Rune_Add(FLAG_COMUNICATUM);
3154 ARX_Player_Rune_Add(FLAG_COSUM);
3155 ARX_Player_Rune_Add(FLAG_FOLGORA);
3156 ARX_Player_Rune_Add(FLAG_FRIDD);
3157 ARX_Player_Rune_Add(FLAG_KAOM);
3158 ARX_Player_Rune_Add(FLAG_MEGA);
3159 ARX_Player_Rune_Add(FLAG_MORTE);
3160 ARX_Player_Rune_Add(FLAG_MOVIS);
3161 ARX_Player_Rune_Add(FLAG_NHI);
3162 ARX_Player_Rune_Add(FLAG_RHAA);
3163 ARX_Player_Rune_Add(FLAG_SPACIUM);
3164 ARX_Player_Rune_Add(FLAG_STREGUM);
3165 ARX_Player_Rune_Add(FLAG_TAAR);
3166 ARX_Player_Rune_Add(FLAG_TEMPUS);
3167 ARX_Player_Rune_Add(FLAG_TERA);
3168 ARX_Player_Rune_Add(FLAG_VISTA);
3169 ARX_Player_Rune_Add(FLAG_VITAE);
3170 ARX_Player_Rune_Add(FLAG_YOK);
3171 }
3172
3173 extern unsigned long LAST_PRECAST_TIME;
3174 extern long sp_wep;
3175 extern long WILL_QUICKLOAD, WILL_QUICKSAVE;
3176 extern long GLOBAL_Player_Room;
3177 extern long cur_mx, cur_pom;
3178 extern long sp_arm, cur_arm;
3179 extern float sp_max_start;
3180
ARX_PLAYER_Invulnerability(long flag)3181 void ARX_PLAYER_Invulnerability(long flag)
3182 {
3183 if (flag)
3184 player.playerflags |= PLAYERFLAGS_INVULNERABILITY;
3185 else
3186 player.playerflags &= ~PLAYERFLAGS_INVULNERABILITY;
3187 }
3188 extern Entity * FlyingOverIO;
3189 extern long cur_sm;
3190 extern void ClearDynLights();
3191
ARX_GAME_Reset(long type)3192 void ARX_GAME_Reset(long type) {
3193
3194 DeadTime = 0;
3195
3196 if(entities.player()) {
3197 entities.player()->speed_modif = 0;
3198 }
3199
3200 LAST_JUMP_ENDTIME = 0;
3201 FlyingOverIO = NULL;
3202 g_miniMap.mapMarkerInit();
3203 ClearDynLights();
3204
3205 if(!DONT_ERASE_PLAYER && entities.player()) {
3206 entities.player()->halo.flags = 0;
3207 }
3208
3209 if(entities.player())entities.player()->gameFlags &= ~GFLAG_INVISIBILITY;
3210 ARX_PLAYER_Invulnerability(0);
3211 GLOBAL_Player_Room = -1;
3212 PLAYER_PARALYSED = 0;
3213
3214 ARX_PLAYER_Reset_Fall();
3215
3216 player.levitate = 0;
3217 Project.telekinesis = 0;
3218 player.onfirmground = 0;
3219 TRUE_FIRM_GROUND = 0;
3220 sp_max_start = 0;
3221 lastposy = -99999999999.f;
3222
3223 ioSteal = NULL;
3224
3225 WILL_QUICKLOAD = 0;
3226 WILL_QUICKSAVE = 0;
3227 GLOBAL_SLOWDOWN = 1.f;
3228
3229 PrecalcIOLighting(NULL, 0, 1);
3230
3231 sp_arm = 0;
3232 cur_arm = 0;
3233 cur_sm = 0;
3234 sp_wep = 0;
3235 sp_max = 0;
3236 cur_mx = 0;
3237 cur_pom = 0;
3238 cur_rf = 0;
3239 cur_mr = 0;
3240
3241
3242 if(entities.player()) {
3243 entities.player()->spellcast_data.castingspell = SPELL_NONE;
3244 }
3245
3246 LAST_PRECAST_TIME = 0;
3247
3248 ARX_INTERFACE_NoteClear();
3249 player.Interface = INTER_LIFE_MANA | INTER_MINIBACK | INTER_MINIBOOK;
3250
3251 // Interactive DynData
3252 ARX_INTERACTIVE_ClearAllDynData();
3253
3254 // PolyBooms
3255 ARX_BOOMS_ClearAllPolyBooms();
3256
3257 // Magical Flares
3258 ARX_MAGICAL_FLARES_KillAll();
3259
3260 // Thrown Objects
3261 ARX_THROWN_OBJECT_KillAll();
3262
3263 // Pathfinder
3264 EERIE_PATHFINDER_Clear();
3265
3266 // Sound
3267 if (!(type & 1))
3268 {
3269 ARX_SOUND_MixerStop(ARX_SOUND_MixerGame);
3270 ARX_SOUND_MixerPause(ARX_SOUND_MixerGame);
3271 ARX_SOUND_MixerResume(ARX_SOUND_MixerGame);
3272 }
3273
3274 // Damages
3275 ARX_DAMAGE_Reset_Blood_Info();
3276 ARX_DAMAGES_Reset();
3277
3278 // Scripts
3279 ARX_SCRIPT_Timer_ClearAll();
3280 ARX_SCRIPT_EventStackClear();
3281 ARX_SCRIPT_ResetAll(0);
3282
3283 // Conversations
3284 ARX_CONVERSATION_Reset();
3285 ARX_CONVERSATION = 0;
3286
3287 // Speech Things
3288 REQUEST_SPEECH_SKIP = 0;
3289 ARX_SPEECH_ClearAll();
3290 ARX_SPEECH_Reset();
3291
3292 // Spells
3293 ARX_SPELLS_Precast_Reset();
3294 ARX_SPELLS_CancelSpellTarget();
3295
3296 ARX_SPELLS_ClearAll();
3297 ARX_SPELLS_ClearAllSymbolDraw();
3298 ARX_SPELLS_ResetRecognition();
3299
3300 // Particles
3301 ARX_PARTICLES_ClearAll();
3302 if(pParticleManager)
3303 pParticleManager->Clear();
3304
3305 // Fogs
3306 ARX_FOGS_TimeReset();
3307 ARX_FOGS_Render();
3308
3309 // Anchors
3310 ANCHOR_BLOCK_Clear();
3311
3312 // Attractors
3313 ARX_SPECIAL_ATTRACTORS_Reset();
3314
3315 // Cinematics
3316 DANAE_KillCinematic();
3317
3318 // Paths
3319 ARX_PATH_ClearAllControled();
3320 ARX_PATH_ClearAllUsePath();
3321
3322 // Player Torch
3323 if (type & 1)
3324 {
3325 if (CURRENT_TORCH) ARX_PLAYER_ClickedOnTorch(CURRENT_TORCH);
3326 }
3327 else
3328 CURRENT_TORCH = NULL;
3329
3330 // Player Quests
3331 ARX_PLAYER_Quest_Init();
3332
3333 // Player Keyring
3334 ARX_KEYRING_Init();
3335
3336 // Player Init
3337 if (!DONT_ERASE_PLAYER)
3338 {
3339 g_miniMap.mapMarkerInit();
3340 GLOBAL_MAGIC_MODE = 1;
3341
3342 // Linked Objects
3343 if (!(type & 2))
3344 {
3345 UnlinkAllLinkedObjects();
3346 ARX_EQUIPMENT_UnEquipAllPlayer();
3347 }
3348
3349 ARX_EQUIPMENT_ReleaseAll(entities.player());
3350
3351 ARX_PLAYER_InitPlayer();
3352 ARX_INTERACTIVE_RemoveGoreOnIO(entities.player());
3353
3354 // default to mouselook on, inventory closed
3355 TRUE_PLAYER_MOUSELOOK_ON = true;
3356
3357 // Player Inventory
3358 CleanInventory();
3359 }
3360
3361 // Misc Player Vars.
3362 ROTATE_START = 0;
3363 BLOCK_PLAYER_CONTROLS = 0;
3364 HERO_SHOW_1ST = -1;
3365 PUSH_PLAYER_FORCE = Vec3f::ZERO;
3366 player.jumplastposition = 0;
3367 player.jumpstarttime = 0;
3368 player.jumpphase = NotJumping;
3369 player.inzone = NULL;
3370
3371 QuakeFx.intensity = 0.f;
3372 Project.improve = 0;
3373
3374 if (eyeball.exist) eyeball.exist = -100;
3375
3376 if(entities.size() > 0 && entities.player()) {
3377 entities.player()->ouch_time = 0;
3378 entities.player()->invisibility = 0.f;
3379 }
3380
3381 FADEDIR = 0;
3382 FADEDURATION = 0;
3383 FADESTART = 0;
3384 FADECOLOR = Color3f::black;
3385
3386 // GLOBALMods
3387 ARX_GLOBALMODS_Reset();
3388
3389 // Missiles
3390 ARX_MISSILES_ClearAll();
3391
3392 // IO PDL
3393 TOTIOPDL = 0;
3394
3395 // Interface
3396 ARX_INTERFACE_Reset();
3397 ARX_INTERFACE_NoteClear();
3398 Set_DragInter(NULL);
3399 SecondaryInventory = NULL;
3400 TSecondaryInventory = NULL;
3401 MasterCamera.exist = 0;
3402 CHANGE_LEVEL_ICON = -1;
3403
3404 CAMERACONTROLLER = NULL;
3405
3406 // Kill Script Loaded IO
3407 CleanScriptLoadedIO();
3408
3409 // ARX Timer
3410 arxtime.init();
3411
3412 ClearTileLights();
3413 }
3414
ARX_PLAYER_Reset_Fall()3415 void ARX_PLAYER_Reset_Fall()
3416 {
3417 FALLING_TIME = 0;
3418 Falling_Height = 50.f;
3419 player.falling = 0;
3420 }
3421
3422
3423
3424 float sp_max_y[64];
3425 Color sp_max_col[64];
3426 char sp_max_ch[64];
3427 long sp_max_nb;
Manage_sp_max()3428 void Manage_sp_max()
3429 {
3430 float v = float(arxtime) - sp_max_start;
3431
3432 if ((sp_max_start != 0) && (v < 20000))
3433 {
3434 float modi = (20000 - v) * ( 1.0f / 2000 ) * ( 1.0f / 10 );
3435 float sizX = 16;
3436 float px = (float)DANAECENTERX - (float)sp_max_nb * ( 1.0f / 2 ) * sizX;
3437 float py = (float)DANAECENTERY;
3438
3439 for (long i = 0; i < sp_max_nb; i++)
3440 {
3441 float dx = px + sizX * (float)i;
3442 float dy = py + sp_max_y[i];
3443 sp_max_y[i] = EEsin(dx + (float)float(arxtime) * ( 1.0f / 100 )) * 30.f * modi;
3444 std::string tex( 1, sp_max_ch[i] );
3445
3446 UNICODE_ARXDrawTextCenter( hFontInBook, dx - 1, dy - 1, tex, Color::none );
3447 UNICODE_ARXDrawTextCenter( hFontInBook, dx + 1, dy + 1, tex, Color::none );
3448 UNICODE_ARXDrawTextCenter( hFontInBook, dx, dy, tex, sp_max_col[i] );
3449
3450 }
3451 }
3452 }
3453