/* =========================================================================== ARX FATALIS GPL Source Code Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company. This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code'). Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see . In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ ////////////////////////////////////////////////////////////////////////////////////// // @@ @@@ @@@ @@ @@@@@ // // @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ // // @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ // // @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ // // @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ // // @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ // // @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ // // @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ // // @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ // // @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ // // @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ // //@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ // //@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ // //@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ // //@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ // //@@@ @@@ @@@ @@@@@ @@ @@@ // // @@@ @@@ @@ @@ STUDIOS // ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// // ARX_Equipment ////////////////////////////////////////////////////////////////////////////////////// // // Description: // ARX_Equipment // // Updates: (date) (person) (update) // // Code: Cyril Meynier // // Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved ////////////////////////////////////////////////////////////////////////////////////// #include #include #include "ARX_Equipment.h" #include "HERMESMain.h" #include "EERIEMath.h" #include "EERIEObject.h" #include "EERIEMeshTweak.h" #include "ARX_NPC.h" #include "ARX_Sound.h" #include "ARX_Collisions.h" #include "ARX_Particles.h" #include "ARX_Damages.h" #include "ARX_interactive.h" #include "ARX_interface.h" #include "ARX_script.h" #include "EERIELinkedObj.h" #define _CRTDBG_MAP_ALLOC #include typedef struct { char name[64]; } EQUIP_INFO; #define SP_SPARKING 1 #define SP_BLOODY 2 extern float PLAYER_BASE_HEIGHT; extern long TRUEFIGHT; extern long GAME_EDITOR; extern EERIE_3D PUSH_PLAYER_FORCE; extern long HERO_SHOW_1ST; extern long EXTERNALVIEW; extern EERIE_3DOBJ * arrowobj; EQUIP_INFO equipinfo[IO_EQUIPITEM_ELEMENT_Number]; //*********************************************************************************************** // Returns the object type flag corresponding to a string //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** unsigned long ARX_EQUIPMENT_GetObjectTypeFlag(char * temp) { if (!temp) return 0; char c = temp[0]; if ((temp[0] >= 'A') && (temp[0] <= 'Z')) c = _tolower(temp[0]); switch (c) { case 'w': return OBJECT_TYPE_WEAPON; case 'd': return OBJECT_TYPE_DAGGER; case '1': return OBJECT_TYPE_1H; case '2': return OBJECT_TYPE_2H; case 'b': return OBJECT_TYPE_BOW; case 's': return OBJECT_TYPE_SHIELD; case 'f': return OBJECT_TYPE_FOOD; case 'g': return OBJECT_TYPE_GOLD; case 'r': return OBJECT_TYPE_RING; case 'a': return OBJECT_TYPE_ARMOR; case 'h': return OBJECT_TYPE_HELMET; case 'l': return OBJECT_TYPE_LEGGINGS; } return 0; } //*********************************************************************************************** // Releases Equiped Id from player //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** void ARX_EQUIPMENT_Release(long id) { if (id) { for (long i = 0; i < MAX_EQUIPED; i++) { if (player.equiped[i] == id) { player.equiped[i] = 0; } } } } //*********************************************************************************************** // Releases all id equipments in IO io //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** void ARX_EQUIPMENT_ReleaseAll(INTERACTIVE_OBJ * io) { if (io) ARX_EQUIPMENT_ReleaseEquipItem(io); } extern long EXITING; //*********************************************************************************************** // Recreates player mesh from scratch //*********************************************************************************************** void ARX_EQUIPMENT_RecreatePlayerMesh() { if (EXITING) return; INTERACTIVE_OBJ * io = inter.iobj[0]; if (io == NULL) return; if (io->obj != hero) { ReleaseEERIE3DObj(io->obj); } char tex[256]; char tex1[256]; sprintf(tex1, "%sGraph\\Obj3D\\Textures\\", Project.workingdir); MakeDir(tex, "graph\\Obj3D\\Interactive\\NPC\\human_base\\human_base.teo"); io->obj = TheoToEerie_Fast(tex1, tex, TTE_NO_PHYSICS_BOX | TTE_NPC); long sel_ = -1; long i; char pathh[256]; if ((player.equiped[EQUIP_SLOT_HELMET] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_HELMET])) { INTERACTIVE_OBJ * tweaker = inter.iobj[player.equiped[EQUIP_SLOT_HELMET]]; if (tweaker) { if (tweaker->tweakerinfo->filename[0] != 0) { sprintf(pathh, "%s\\Graph\\Obj3D\\Interactive\\NPC\\human_base\\tweaks\\%s", Project.workingdir, tweaker->tweakerinfo->filename); EERIE_MESH_TWEAK_Do(io, TWEAK_HEAD, pathh); } if ((tweaker->tweakerinfo->skintochange[0] != 0) && (tweaker->tweakerinfo->skinchangeto[0] != 0)) { char path[256]; sprintf(path, "Graph\\Obj3D\\Textures\\%s.bmp", tweaker->tweakerinfo->skinchangeto); TextureContainer * temp = MakeTCFromFile(path, 1); if (temp) temp->Restore(GDevice); long mapidx = ObjectAddMap(io->obj, temp); // retreives head sel for (i = 0; i < io->obj->nbselections; i++) { if (!stricmp(io->obj->selections[i].name, "head")) { sel_ = i; break; } } long textochange = -1; for (i = 0; i < io->obj->nbmaps; i++) { if (!stricmp(tweaker->tweakerinfo->skintochange, GetName(io->obj->texturecontainer[i]->m_strName))) textochange = i; } if ((sel_ != -1) && (textochange != -1)) for (i = 0; i < io->obj->nbfaces; i++) { if ((IsInSelection(io->obj, io->obj->facelist[i].vid[0], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[1], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[2], sel_) != -1)) { if (io->obj->facelist[i].texid == textochange) io->obj->facelist[i].texid = (short)mapidx; } } } } } if ((player.equiped[EQUIP_SLOT_ARMOR] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { INTERACTIVE_OBJ * tweaker = inter.iobj[player.equiped[EQUIP_SLOT_ARMOR]]; if (tweaker) { if (tweaker->tweakerinfo->filename[0] != 0) { sprintf(pathh, "%s\\Graph\\Obj3D\\Interactive\\NPC\\human_base\\tweaks\\%s", Project.workingdir, tweaker->tweakerinfo->filename); EERIE_MESH_TWEAK_Do(io, TWEAK_TORSO, pathh); } if ((tweaker->tweakerinfo->skintochange[0] != 0) && (tweaker->tweakerinfo->skinchangeto[0] != 0)) { char path[256]; sprintf(path, "Graph\\Obj3D\\Textures\\%s.bmp", tweaker->tweakerinfo->skinchangeto); TextureContainer * temp = MakeTCFromFile(path, 1); if (temp) temp->Restore(GDevice); long mapidx = ObjectAddMap(io->obj, temp); // retreives head sel for (i = 0; i < io->obj->nbselections; i++) { if (!stricmp(io->obj->selections[i].name, "chest")) { sel_ = i; break; } } long textochange = -1; for (i = 0; i < io->obj->nbmaps; i++) { if (!stricmp(tweaker->tweakerinfo->skintochange, GetName(io->obj->texturecontainer[i]->m_strName))) textochange = i; } if ((sel_ != -1) && (textochange != -1)) for (i = 0; i < io->obj->nbfaces; i++) { if ((IsInSelection(io->obj, io->obj->facelist[i].vid[0], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[1], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[2], sel_) != -1)) { if (io->obj->facelist[i].texid == textochange) io->obj->facelist[i].texid = (short)mapidx; } } } } } if ((player.equiped[EQUIP_SLOT_LEGGINGS] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_LEGGINGS])) { INTERACTIVE_OBJ * tweaker = inter.iobj[player.equiped[EQUIP_SLOT_LEGGINGS]]; if (tweaker) { if (tweaker->tweakerinfo->filename[0] != 0) { sprintf(pathh, "%s\\Graph\\Obj3D\\Interactive\\NPC\\human_base\\tweaks\\%s", Project.workingdir, tweaker->tweakerinfo->filename); EERIE_MESH_TWEAK_Do(io, TWEAK_LEGS, pathh); } if ((tweaker->tweakerinfo->skintochange[0] != 0) && (tweaker->tweakerinfo->skinchangeto[0] != 0)) { char path[256]; sprintf(path, "Graph\\Obj3D\\Textures\\%s.bmp", tweaker->tweakerinfo->skinchangeto); TextureContainer * temp = MakeTCFromFile(path, 1); if (temp) temp->Restore(GDevice); long mapidx = ObjectAddMap(io->obj, temp); // retreives head sel for (i = 0; i < io->obj->nbselections; i++) { if (!stricmp(io->obj->selections[i].name, "leggings")) { sel_ = i; break; } } long textochange = -1; for (i = 0; i < io->obj->nbmaps; i++) { if (!stricmp(tweaker->tweakerinfo->skintochange, GetName(io->obj->texturecontainer[i]->m_strName))) textochange = i; } if ((sel_ != -1) && (textochange != -1)) for (i = 0; i < io->obj->nbfaces; i++) { if ((IsInSelection(io->obj, io->obj->facelist[i].vid[0], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[1], sel_) != -1) && (IsInSelection(io->obj, io->obj->facelist[i].vid[2], sel_) != -1)) { if (io->obj->facelist[i].texid == textochange) io->obj->facelist[i].texid = (short)mapidx; } } } } } INTERACTIVE_OBJ * target = inter.iobj[0]; INTERACTIVE_OBJ * toequip = NULL; if (!target) return; for (i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { toequip = inter.iobj[player.equiped[i]]; if (toequip) { if (toequip->type_flags & (OBJECT_TYPE_DAGGER | OBJECT_TYPE_1H | OBJECT_TYPE_2H | OBJECT_TYPE_BOW)) { if (player.Interface & INTER_COMBATMODE) { ARX_EQUIPMENT_AttachPlayerWeaponToHand(); } else { EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "WEAPON_ATTACH", "PRIMARY_ATTACH", toequip); // } } else if (toequip->type_flags & OBJECT_TYPE_SHIELD) { if (player.equiped[EQUIP_SLOT_SHIELD] != 0) { EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "SHIELD_ATTACH", "SHIELD_ATTACH", toequip); } } } } } ARX_PLAYER_Restore_Skin(); HERO_SHOW_1ST = -1; if (EXTERNALVIEW) { ARX_INTERACTIVE_Show_Hide_1st(inter.iobj[0], 0); } else { ARX_INTERACTIVE_Show_Hide_1st(inter.iobj[0], 1); } ARX_INTERACTIVE_HideGore(inter.iobj[0], 1); EERIE_Object_Precompute_Fast_Access(hero); EERIE_Object_Precompute_Fast_Access(inter.iobj[0]->obj); ARX_INTERACTIVE_RemoveGoreOnIO(inter.iobj[0]); } void ARX_EQUIPMENT_UnEquipAllPlayer() { for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i]) && (ValidIONum(player.equiped[i]))) { ARX_EQUIPMENT_UnEquip(inter.iobj[0], inter.iobj[player.equiped[i]]); } } ARX_PLAYER_ComputePlayerFullStats(); } bool ARX_EQUIPMENT_IsPlayerEquip(INTERACTIVE_OBJ * _pIO) { INTERACTIVE_OBJ * io = inter.iobj[0]; if (io == NULL) return false; if (io != inter.iobj[0]) return false; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { INTERACTIVE_OBJ * toequip = inter.iobj[player.equiped[i]]; if (toequip == _pIO) { return true; } } } return false; } //*********************************************************************************************** // flags & 1 == destroyed ! //*********************************************************************************************** void ARX_EQUIPMENT_UnEquip(INTERACTIVE_OBJ * target, INTERACTIVE_OBJ * tounequip, long flags) { if (target == NULL) return; if (tounequip == NULL) return; if (target != inter.iobj[0]) return; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i]) && (inter.iobj[player.equiped[i]] == tounequip)) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(target->obj, tounequip->obj); ARX_EQUIPMENT_Release(player.equiped[i]); target->bbox1.x = 9999; target->bbox2.x = -9999; if (!flags & 1) { if (DRAGINTER == NULL) { ARX_SOUND_PlayInterface(SND_INVSTD); Set_DragInter(tounequip); } else if (!CanBePutInInventory(tounequip)) { PutInFrontOfPlayer(tounequip, 1); } } EVENT_SENDER = tounequip; SendIOScriptEvent(inter.iobj[0], SM_EQUIPOUT, "", NULL); EVENT_SENDER = inter.iobj[0]; SendIOScriptEvent(tounequip, SM_EQUIPOUT, "", NULL); } } if ((tounequip->type_flags & OBJECT_TYPE_HELMET) || (tounequip->type_flags & OBJECT_TYPE_ARMOR) || (tounequip->type_flags & OBJECT_TYPE_LEGGINGS)) ARX_EQUIPMENT_RecreatePlayerMesh(); } //*********************************************************************************************** //*********************************************************************************************** void ARX_EQUIPMENT_AttachPlayerWeaponToHand() { INTERACTIVE_OBJ * target = inter.iobj[0]; INTERACTIVE_OBJ * toequip = NULL; if (!target) return; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { toequip = inter.iobj[player.equiped[i]]; if (toequip) { if ((toequip->type_flags & OBJECT_TYPE_DAGGER) || (toequip->type_flags & OBJECT_TYPE_1H) || (toequip->type_flags & OBJECT_TYPE_2H) || (toequip->type_flags & OBJECT_TYPE_BOW) ) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(target->obj, toequip->obj); EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "PRIMARY_ATTACH", "PRIMARY_ATTACH", toequip); // return; } } } } } //*********************************************************************************************** //*********************************************************************************************** void ARX_EQUIPMENT_AttachPlayerWeaponToBack() { INTERACTIVE_OBJ * target = inter.iobj[0]; INTERACTIVE_OBJ * toequip = NULL; if (!target) return; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { toequip = inter.iobj[player.equiped[i]]; if (toequip) { if ((toequip->type_flags & OBJECT_TYPE_DAGGER) || (toequip->type_flags & OBJECT_TYPE_1H) || (toequip->type_flags & OBJECT_TYPE_2H) || (toequip->type_flags & OBJECT_TYPE_BOW) ) { if (toequip->type_flags & OBJECT_TYPE_BOW) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(target->obj, toequip->obj); EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "WEAPON_ATTACH", "TEST", toequip); // return; } EERIE_LINKEDOBJ_UnLinkObjectFromObject(target->obj, toequip->obj); EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "WEAPON_ATTACH", "PRIMARY_ATTACH", toequip); // return; } } } } } //*********************************************************************************************** //*********************************************************************************************** long ARX_EQUIPMENT_GetPlayerWeaponType() { INTERACTIVE_OBJ * io = inter.iobj[0]; if (!io) return WEAPON_BARE; if ((player.equiped[EQUIP_SLOT_WEAPON] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { INTERACTIVE_OBJ * toequip = inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]; if (toequip) { if (toequip->type_flags & OBJECT_TYPE_DAGGER) return WEAPON_DAGGER; if (toequip->type_flags & OBJECT_TYPE_1H) return WEAPON_1H; if (toequip->type_flags & OBJECT_TYPE_2H) return WEAPON_2H; if (toequip->type_flags & OBJECT_TYPE_BOW) return WEAPON_BOW; } } return WEAPON_BARE; } //*********************************************************************************************** //*********************************************************************************************** void ARX_EQUIPMENT_LaunchPlayerUnReadyWeapon() { INTERACTIVE_OBJ * io = inter.iobj[0]; if (!io) return; ANIM_HANDLE * anim = io->anims[ANIM_BARE_UNREADY]; long type = ARX_EQUIPMENT_GetPlayerWeaponType(); switch (type) { case WEAPON_DAGGER: anim = io->anims[ANIM_DAGGER_UNREADY_PART_1]; break; case WEAPON_1H: anim = io->anims[ANIM_1H_UNREADY_PART_1]; break; case WEAPON_2H: anim = io->anims[ANIM_2H_UNREADY_PART_1]; break; case WEAPON_BOW: { anim = io->anims[ANIM_MISSILE_UNREADY_PART_1]; if (arrowobj) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); } } break; default: anim = io->anims[ANIM_BARE_UNREADY]; break; } AcquireLastAnim(io); ANIM_Set(&io->animlayer[1], anim); } //*********************************************************************************************** //*********************************************************************************************** float ARX_EQUIPMENT_ComputeDamages(INTERACTIVE_OBJ * io_source, INTERACTIVE_OBJ * io_weapon, INTERACTIVE_OBJ * io_target, float ratioaim, EERIE_3D * position) { EVENT_SENDER = io_source; SendIOScriptEvent(io_target, SM_AGGRESSION, "", NULL); if ((!io_source) || (!io_target)) return 0.f; if (!(io_target->ioflags & IO_NPC)) { if (io_target->ioflags & IO_FIX) { if (io_source == inter.iobj[0]) ARX_DAMAGES_DamageFIX(io_target, player.Full_damages, 0, 0); else if (io_source->ioflags & IO_NPC) ARX_DAMAGES_DamageFIX(io_target, io_source->_npcdata->damages, GetInterNum(io_source), 0); else ARX_DAMAGES_DamageFIX(io_target, 1, GetInterNum(io_source), 0); } return 0.f; } float attack, ac, damages; float backstab = 1.f; char wmat[64]; char amat[64]; strcpy(wmat, "BARE"); strcpy(amat, "FLESH"); BOOL critical = FALSE; if (io_source == inter.iobj[0]) { if ((player.equiped[EQUIP_SLOT_WEAPON] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { INTERACTIVE_OBJ * io = inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]; if ((io) && (io->weaponmaterial)) { strcpy(wmat, io->weaponmaterial); } } attack = player.Full_damages; if (rnd() * 100 <= (float)(player.Full_Attribute_Dexterity - 9) * 2.f + (float)(player.Full_Skill_Close_Combat * DIV5)) { if (SendIOScriptEvent(io_source, SM_CRITICAL, "", NULL) != REFUSE) critical = TRUE; } else critical = FALSE; damages = attack * ratioaim; if (io_target->_npcdata->npcflags & NPCFLAG_BACKSTAB) { if (rnd() * 100.f <= player.Full_Skill_Stealth * DIV2) { if (SendIOScriptEvent(io_source, SM_BACKSTAB, "", NULL) != REFUSE) backstab = 1.5f; } } } else { if (!(io_source->ioflags & IO_NPC)) return 0.f; // no NPC source... if (io_source->weaponmaterial) { strcpy(wmat, io_source->weaponmaterial); } if (io_source->_npcdata->weapon != NULL) { INTERACTIVE_OBJ * iow = (INTERACTIVE_OBJ *)io_source->_npcdata->weapon; if (iow->weaponmaterial) strcpy(wmat, iow->weaponmaterial); } attack = io_source->_npcdata->tohit; if (GAME_EDITOR) damages = io_source->_npcdata->damages * ratioaim; else damages = io_source->_npcdata->damages * ratioaim * (rnd() * DIV2 + 0.5f); long value = ARX_SPELLS_GetSpellOn(io_source, SPELL_CURSE); if (value >= 0) { damages *= (spells[value].caster_level * 0.05f); } if (rnd() * 100 <= io_source->_npcdata->critical) { if (SendIOScriptEvent(io_source, SM_CRITICAL, "", NULL) != REFUSE) critical = TRUE; } else critical = FALSE; if (rnd() * 100.f <= (float)io_source->_npcdata->backstab_skill) { if (SendIOScriptEvent(io_source, SM_BACKSTAB, "", NULL) != REFUSE) backstab = 1.5f; } } float absorb; if (io_target == inter.iobj[0]) { ac = player.Full_armor_class; absorb = player.Full_Skill_Defense * DIV2; } else { ac = ARX_INTERACTIVE_GetArmorClass(io_target); absorb = io_target->_npcdata->absorb; long value = ARX_SPELLS_GetSpellOn(io_target, SPELL_CURSE); if (value >= 0) { float modif = (spells[value].caster_level * 0.05f); ac *= modif; absorb *= modif; } } if (io_target->armormaterial) { strcpy(amat, io_target->armormaterial); } if (io_target == inter.iobj[0]) { if ((player.equiped[EQUIP_SLOT_ARMOR] > 0) && ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { INTERACTIVE_OBJ * io = inter.iobj[player.equiped[EQUIP_SLOT_ARMOR]]; if ((io) && (io->armormaterial)) { strcpy(amat, io->armormaterial); } } } float dmgs = damages * backstab; dmgs -= dmgs * (absorb * DIV100); EERIE_3D pos; pos.x = io_target->pos.x; pos.y = io_target->pos.y; pos.z = io_target->pos.z; float power; power = dmgs * DIV20; if (power > 1.f) power = 1.f; if (!stricmp(wmat, "BARE")) power = power * 0.1f + 0.9f; else power = power * 0.1f + 0.9f; ARX_SOUND_PlayCollision(amat, wmat, power, 1.f, &pos, io_source); float chance = 100.f - (ac - attack); float dice = rnd() * 100.f; if (dice <= chance) { strcpy(amat, "FLESH"); ARX_SOUND_PlayCollision(amat, wmat, power, 1.f, &pos, io_source); EERIE_3D pos; pos.x = io_target->pos.x; pos.y = io_target->pos.y + io_target->physics.cyl.height * DIV2; pos.z = io_target->pos.z; if (dmgs > 0.f) { if (critical) { dmgs *= 1.5f; } if (io_target == inter.iobj[0]) { EERIE_3D ppos; ppos.x = io_source->pos.x - player.pos.x; ppos.y = io_source->pos.y - player.pos.y - PLAYER_BASE_HEIGHT; ppos.z = io_source->pos.z - player.pos.z; Vector_Normalize(&ppos); //------- player push START EERIE_3D push; Vector_Copy(&push, &ppos); push.x *= -dmgs * DIV11; push.y *= -dmgs * DIV30; push.z *= -dmgs * DIV11; PUSH_PLAYER_FORCE.x += push.x; PUSH_PLAYER_FORCE.y += push.y; PUSH_PLAYER_FORCE.z += push.z; //------- player push END ppos.x *= 60.f; ppos.y *= 60.f; ppos.z *= 60.f; ppos.x += ACTIVECAM->pos.x; ppos.y += ACTIVECAM->pos.y; ppos.z += ACTIVECAM->pos.z; ARX_DAMAGES_SCREEN_SPLATS_Add(&ppos, dmgs); ARX_DAMAGES_DamagePlayer(dmgs, 0, GetInterNum(io_source), &io_target->pos); ARX_DAMAGES_DamagePlayerEquipment(dmgs); } else { EERIE_3D ppos; ppos.x = io_source->pos.x - io_target->pos.x; ppos.y = io_source->pos.y - io_target->pos.y; ppos.z = io_source->pos.z - io_target->pos.z; if (io_target == inter.iobj[0]) ppos.y -= PLAYER_BASE_HEIGHT; Vector_Normalize(&ppos); //------- player NPC START EERIE_3D push; Vector_Copy(&push, &ppos); push.x *= -dmgs; push.y *= -dmgs; push.z *= -dmgs; io_target->forcedmove.x += push.x; io_target->forcedmove.y += push.y; io_target->forcedmove.z += push.z; //------- player NPC END if (position) ARX_DAMAGES_DamageNPC(io_target, dmgs, GetInterNum(io_source), 0, position); else ARX_DAMAGES_DamageNPC(io_target, dmgs, GetInterNum(io_source), 0, &io_target->pos); } } return dmgs; } return 0.f; } //*********************************************************************************************** // flags & 1 = blood spawn only //----------------------------------------------------------------------------------------------- //*********************************************************************************************** BOOL ARX_EQUIPMENT_Strike_Check(INTERACTIVE_OBJ * io_source, INTERACTIVE_OBJ * io_weapon, float ratioaim, long flags, long targ) { if (TRUEFIGHT) ratioaim = 1.f; BOOL ret = FALSE; long source = GetInterNum(io_source); long weapon = GetInterNum(io_weapon); EERIE_SPHERE sphere; EERIE_3D * v0; EXCEPTIONS_LIST_Pos = 0; float rad; long nbact = io_weapon->obj->nbaction; float drain_life = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_DRAIN_LIFE); float paralyse = ARX_EQUIPMENT_GetSpecialValue(io_weapon, IO_SPECIAL_ELEM_PARALYZE); for (long j = 0; j < nbact; j++) { if (!ValidIONum(weapon)) return FALSE; rad = GetHitValue(io_weapon->obj->actionlist[j].name); if (rad == -1) continue; v0 = &io_weapon->obj->vertexlist3[io_weapon->obj->actionlist[j].idx].v; sphere.origin.x = v0->x; sphere.origin.y = v0->y; sphere.origin.z = v0->z; sphere.radius = rad; if (source != 0) sphere.radius += 15.f; if (CheckEverythingInSphere(&sphere, source, targ)) { for (long jj = 0; jj < MAX_IN_SPHERE_Pos; jj++) { float dmgs = 0.f; if (ValidIONum(EVERYTHING_IN_SPHERE[jj]) && (!(inter.iobj[EVERYTHING_IN_SPHERE[jj]]->ioflags & IO_BODY_CHUNK))) { long HIT_SPARK = 0; EXCEPTIONS_LIST[EXCEPTIONS_LIST_Pos] = EVERYTHING_IN_SPHERE[jj]; EXCEPTIONS_LIST_Pos++; if (EXCEPTIONS_LIST_Pos >= MAX_IN_SPHERE) EXCEPTIONS_LIST_Pos--; INTERACTIVE_OBJ * target = inter.iobj[EVERYTHING_IN_SPHERE[jj]]; EERIE_3D pos; D3DCOLOR color = ARX_OPAQUE_WHITE; long hitpoint = -1; float curdist = 999999.f; EERIE_3D vector; vector.x = sphere.origin.x - target->pos.x; vector.y = (sphere.origin.y - target->pos.y) * DIV2; vector.z = sphere.origin.z - target->pos.z; float t = 1.f / TRUEVector_Magnitude(&vector); vector.x *= t; vector.y *= t; vector.z *= t; for (long ii = 0; ii < target->obj->nbfaces; ii++) { if (target->obj->facelist[ii].facetype & POLY_HIDE) continue; float dist = TRUEEEDistance3D(&sphere.origin, &target->obj->vertexlist3[target->obj->facelist[ii].vid[0]].v); if (dist < curdist) { hitpoint = target->obj->facelist[ii].vid[0]; curdist = dist; } } if (hitpoint >= 0) { if (target->ioflags & IO_NPC) color = target->_npcdata->blood_color; else color = 0xFFFFFFFF; Vector_Copy(&pos, &target->obj->vertexlist3[hitpoint].v); } else ARX_CHECK_NO_ENTRY(); if (!(flags & 1)) { EERIE_3D posi; if (hitpoint >= 0) { Vector_Copy(&posi, &target->obj->vertexlist3[hitpoint].v); dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, io_weapon, target, ratioaim, &posi); } else { dmgs = ARX_EQUIPMENT_ComputeDamages(io_source, io_weapon, target, ratioaim); } if (target->ioflags & IO_NPC) { ret = TRUE; target->spark_n_blood = 0; target->_npcdata->SPLAT_TOT_NB = 0; if (drain_life > 0.f) { float life_gain = __min(dmgs, drain_life); life_gain = __min(life_gain, target->_npcdata->life); life_gain = __max(life_gain, 0.f); ARX_DAMAGES_HealInter(io_source, life_gain); } if (paralyse > 0.f) { float ptime = __min(dmgs * 1000.f, paralyse); ARX_SPELLS_Launch(SPELL_PARALYSE, weapon, SPELLCAST_FLAG_NOMANA | SPELLCAST_FLAG_NOCHECKCANCAST , 5, EVERYTHING_IN_SPHERE[jj], (long)(ptime)); } } if (io_source == inter.iobj[0]) { ARX_DAMAGES_DurabilityCheck(io_weapon, 0.2f); } } if ((dmgs > 0.f) || ((target->ioflags & IO_NPC) && (target->spark_n_blood == SP_BLOODY))) { if (target->ioflags & IO_NPC) { target->spark_n_blood = SP_BLOODY; if (!(flags & 1)) { ARX_PARTICLES_Spawn_Splat(&pos, dmgs, color, hitpoint, target); EERIE_SPHERE sp; float power; power = (dmgs * DIV40) + 0.7f; EERIE_3D vect; vect.x = target->obj->vertexlist3[hitpoint].v.x - io_source->pos.x; vect.y = 0; vect.z = target->obj->vertexlist3[hitpoint].v.z - io_source->pos.z; Vector_Normalize(&vect); sp.origin.x = target->obj->vertexlist3[hitpoint].v.x + vect.x * 30.f; sp.origin.y = target->obj->vertexlist3[hitpoint].v.y; sp.origin.z = target->obj->vertexlist3[hitpoint].v.z + vect.z * 30.f; sp.radius = 3.5f * power * 20; if (CheckAnythingInSphere(&sp, 0, 1)) { EERIE_RGB rgb; rgb.r = (float)((long)((color >> 16) & 255)) * DIV255; rgb.g = (float)((long)((color >> 8) & 255)) * DIV255; rgb.b = (float)((long)((color) & 255)) * DIV255; SpawnGroundSplat(&sp, &rgb, 30, 1); } } if (target == inter.iobj[0]) ARX_DAMAGES_SCREEN_SPLATS_Add(&pos, dmgs); ARX_PARTICLES_Spawn_Blood2(&pos, dmgs, color, hitpoint, target); if (!ValidIONum(weapon)) io_weapon = NULL; } else { if (target->ioflags & IO_ITEM) ARX_PARTICLES_Spawn_Spark(&pos, rnd() * 3.f, 0); else ARX_PARTICLES_Spawn_Spark(&pos, rnd() * 30.f, 0); ARX_NPC_SpawnAudibleSound(&pos, io_source); if (io_source == inter.iobj[0]) HIT_SPARK = 1; } } else if ((target->ioflags & IO_NPC) && ((dmgs <= 0.f) || (target->spark_n_blood == SP_SPARKING))) { long nb; if (target->spark_n_blood == SP_SPARKING) nb = (long)(float)(rnd() * 3.f); else nb = 30; if (target->ioflags & IO_ITEM) nb = 1; ARX_PARTICLES_Spawn_Spark(&pos, (float)nb, 0); ARX_NPC_SpawnAudibleSound(&pos, io_source); target->spark_n_blood = SP_SPARKING; if (!(target->ioflags & IO_NPC)) HIT_SPARK = 1; } else if ((dmgs <= 0.f) && ((target->ioflags & IO_FIX) || (target->ioflags & IO_ITEM))) { long nb; if (target->spark_n_blood == SP_SPARKING) nb = (long)(float)(rnd() * 3.f); else nb = 30; if (target->ioflags & IO_ITEM) nb = 1; ARX_PARTICLES_Spawn_Spark(&pos, (float)nb, 0); ARX_NPC_SpawnAudibleSound(&pos, io_source); target->spark_n_blood = SP_SPARKING; if (!(target->ioflags & IO_NPC)) HIT_SPARK = 1; } if (HIT_SPARK) { if (!(io_source->aflags & IO_NPC_AFLAG_HIT_BACKGROUND)) { ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f); io_source->aflags |= IO_NPC_AFLAG_HIT_BACKGROUND; if (!ValidIONum(weapon)) { io_weapon = NULL; } else { char weapon_material[64] = ""; if (io_weapon && io_weapon->weaponmaterial) strcpy(weapon_material, io_weapon->weaponmaterial); else strcpy(weapon_material, "METAL"); char bkg_material[128]; if (ARX_MATERIAL_GetNameById(target->material, bkg_material)) ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, &sphere.origin, NULL); } } } } } } EERIEPOLY * ep; if (ep = CheckBackgroundInSphere(&sphere)) { if (io_source == inter.iobj[0]) { if (!(io_source->aflags & IO_NPC_AFLAG_HIT_BACKGROUND)) { ARX_DAMAGES_DurabilityCheck(io_weapon, 1.f); io_source->aflags |= IO_NPC_AFLAG_HIT_BACKGROUND; if (!ValidIONum(weapon)) { io_weapon = NULL; } else { char weapon_material[64] = ""; if (io_weapon && io_weapon->weaponmaterial) strcpy(weapon_material, io_weapon->weaponmaterial); else strcpy(weapon_material, "METAL"); char bkg_material[64] = "EARTH"; if (ep && ep->tex && ep->tex->m_texName) GetMaterialString(ep->tex->m_texName, bkg_material); ARX_SOUND_PlayCollision(weapon_material, bkg_material, 1.f, 1.f, &sphere.origin, io_source); } } } ARX_PARTICLES_Spawn_Spark(&sphere.origin, rnd() * 10.f, 0); ARX_NPC_SpawnAudibleSound(&sphere.origin, io_source); } } return ret; } //*********************************************************************************************** //----------------------------------------------------------------------------------------------- //*********************************************************************************************** void ARX_EQUIPMENT_LaunchPlayerReadyWeapon() { INTERACTIVE_OBJ * io = inter.iobj[0]; if (!io) return; long type = ARX_EQUIPMENT_GetPlayerWeaponType(); ANIM_HANDLE * anim = NULL; switch (type) { case WEAPON_DAGGER: anim = io->anims[ANIM_DAGGER_READY_PART_1]; break; case WEAPON_1H: anim = io->anims[ANIM_1H_READY_PART_1]; break; case WEAPON_2H: if (player.equiped[EQUIP_SLOT_SHIELD] == 0) anim = io->anims[ANIM_2H_READY_PART_1]; break; case WEAPON_BOW: if (player.equiped[EQUIP_SLOT_SHIELD] == 0) anim = io->anims[ANIM_MISSILE_READY_PART_1]; break; default: anim = io->anims[ANIM_BARE_READY]; break; } AcquireLastAnim(io); ANIM_Set(&io->animlayer[1], anim); } //*********************************************************************************************** //----------------------------------------------------------------------------------------------- //*********************************************************************************************** void ARX_EQUIPMENT_UnEquipPlayerWeapon() { if ((player.equiped[EQUIP_SLOT_WEAPON] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { INTERACTIVE_OBJ * pioOldDragInter; pioOldDragInter = DRAGINTER; DRAGINTER = inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]; if (DRAGINTER) ARX_SOUND_PlayInterface(SND_INVSTD); ARX_EQUIPMENT_UnEquip(inter.iobj[0], inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]); DRAGINTER = pioOldDragInter; } player.equiped[EQUIP_SLOT_WEAPON] = 0; } bool bRing = false; //*********************************************************************************************** //----------------------------------------------------------------------------------------------- //*********************************************************************************************** void ARX_EQUIPMENT_Equip(INTERACTIVE_OBJ * target, INTERACTIVE_OBJ * toequip) { if (!target) return; if (!toequip) return; if (target != inter.iobj[0]) return; long validid = -1; for (long i = 0; i < inter.nbmax; i++) { if (inter.iobj[i] == toequip) { validid = i; break; } } if (validid == -1) return; RemoveFromAllInventories(toequip); toequip->show = SHOW_FLAG_ON_PLAYER; // on player if (toequip == DRAGINTER) Set_DragInter(NULL); if ((toequip->type_flags & OBJECT_TYPE_DAGGER) || (toequip->type_flags & OBJECT_TYPE_1H) || (toequip->type_flags & OBJECT_TYPE_2H) || (toequip->type_flags & OBJECT_TYPE_BOW) ) { if ((player.equiped[EQUIP_SLOT_WEAPON] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]); } player.equiped[EQUIP_SLOT_WEAPON] = (short)validid; if (toequip->type_flags & OBJECT_TYPE_BOW) { EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "WEAPON_ATTACH", "TEST", toequip); // } else { EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "WEAPON_ATTACH", "PRIMARY_ATTACH", toequip); // } if ((toequip->type_flags & OBJECT_TYPE_2H) || (toequip->type_flags & OBJECT_TYPE_BOW)) { if (player.equiped[EQUIP_SLOT_SHIELD] != 0) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_SHIELD]]); } } } else if (toequip->type_flags & OBJECT_TYPE_SHIELD) { if ((player.equiped[EQUIP_SLOT_SHIELD] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_SHIELD])) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_SHIELD]]); } player.equiped[EQUIP_SLOT_SHIELD] = (short)validid; EERIE_LINKEDOBJ_LinkObjectToObject(target->obj, toequip->obj, "SHIELD_ATTACH", "SHIELD_ATTACH", toequip); if ((player.equiped[EQUIP_SLOT_WEAPON] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_WEAPON])) { if ((inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]->type_flags & OBJECT_TYPE_2H) || (inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]->type_flags & OBJECT_TYPE_BOW)) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_WEAPON]]); } } } else if (toequip->type_flags & OBJECT_TYPE_RING) { // check first, if not already equiped if (!((ValidIONum(player.equiped[EQUIP_SLOT_RING_LEFT]) && (toequip == inter.iobj[player.equiped[EQUIP_SLOT_RING_LEFT]])) || (ValidIONum(player.equiped[EQUIP_SLOT_RING_RIGHT]) && (toequip == inter.iobj[player.equiped[EQUIP_SLOT_RING_RIGHT]])))) { long willequip = -1; if (player.equiped[EQUIP_SLOT_RING_LEFT] == 0) willequip = EQUIP_SLOT_RING_LEFT; if (player.equiped[EQUIP_SLOT_RING_RIGHT] == 0) willequip = EQUIP_SLOT_RING_RIGHT; if (willequip == -1) { if (bRing) { if (ValidIONum(player.equiped[EQUIP_SLOT_RING_RIGHT])) ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_RING_RIGHT]]); willequip = EQUIP_SLOT_RING_RIGHT; } else { if (ValidIONum(player.equiped[EQUIP_SLOT_RING_LEFT])) ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_RING_LEFT]]); willequip = EQUIP_SLOT_RING_LEFT; } bRing = !bRing; } player.equiped[willequip] = (short)validid; } } else if (toequip->type_flags & OBJECT_TYPE_ARMOR) { if ((player.equiped[EQUIP_SLOT_ARMOR] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_ARMOR]]); } player.equiped[EQUIP_SLOT_ARMOR] = (short)validid; } else if (toequip->type_flags & OBJECT_TYPE_LEGGINGS) { if ((player.equiped[EQUIP_SLOT_LEGGINGS] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_LEGGINGS])) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_LEGGINGS]]); } player.equiped[EQUIP_SLOT_LEGGINGS] = (short)validid; } else if (toequip->type_flags & OBJECT_TYPE_HELMET) { if ((player.equiped[EQUIP_SLOT_HELMET] != 0) && (ValidIONum(player.equiped[EQUIP_SLOT_HELMET]))) { ARX_EQUIPMENT_UnEquip(target, inter.iobj[player.equiped[EQUIP_SLOT_HELMET]]); } player.equiped[EQUIP_SLOT_HELMET] = (short)validid; } if ((toequip->type_flags & OBJECT_TYPE_HELMET) || (toequip->type_flags & OBJECT_TYPE_ARMOR) || (toequip->type_flags & OBJECT_TYPE_LEGGINGS)) ARX_EQUIPMENT_RecreatePlayerMesh(); ARX_PLAYER_ComputePlayerFullStats(); } //*********************************************************************************************** // Sets/unsets an object type flag //----------------------------------------------------------------------------------------------- //*********************************************************************************************** void ARX_EQUIPMENT_SetObjectType(INTERACTIVE_OBJ * io, char * temp, long val) { // avoid erroneous objects if (!io) return; // retrieves flag unsigned long flagg = ARX_EQUIPMENT_GetObjectTypeFlag(temp); if (val) // add flag io->type_flags |= flagg; else // remove flag io->type_flags &= ~flagg; } //*********************************************************************************************** // Initializes Equipment infos //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** void ARX_EQUIPMENT_Init() { // IO_EQUIPITEM_ELEMENT_... are Defined in EERIEPOLY.h strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_STRENGTH].name, "strength"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_DEXTERITY].name, "dexterity"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_CONSTITUTION].name, "constitution"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_MIND].name, "intelligence"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Stealth].name, "stealth"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Mecanism].name, "mecanism"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Intuition].name, "intuition"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Etheral_Link].name, "etheral_link"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Object_Knowledge].name, "object_knowledge"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Casting].name, "casting"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Projectile].name, "projectile"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Close_Combat].name, "close_combat"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Defense].name, "defense"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Armor_Class].name, "armor_class"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Resist_Magic].name, "resist_magic"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Resist_Poison].name, "resist_poison"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Critical_Hit].name, "critical_hit"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Damages].name, "damages"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Duration].name, "duration"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_AimTime].name, "aim_time"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Identify_Value].name, "identify_value"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Life].name, "life"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_Mana].name, "mana"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_MaxLife].name, "maxlife"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_MaxMana].name, "maxmana"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_SPECIAL_1].name, "special1"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_SPECIAL_2].name, "special2"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_SPECIAL_3].name, "special3"); strcpy(equipinfo[IO_EQUIPITEM_ELEMENT_SPECIAL_4].name, "special4"); } //*********************************************************************************************** // Releases Equipment Structure //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** void ARX_EQUIPMENT_ReleaseEquipItem(INTERACTIVE_OBJ * io) { if (!io) return; if (!(io->ioflags & IO_ITEM)) return; if (io->_itemdata->equipitem) { free(io->_itemdata->equipitem); io->_itemdata->equipitem = NULL; } } //*********************************************************************************************** // Removes All special equipement properties //----------------------------------------------------------------------------------------------- // VERIFIED (Cyril 2001/10/29) //*********************************************************************************************** void ARX_EQUIPMENT_Remove_All_Special(INTERACTIVE_OBJ * io) { if (!io) return; if (!(io->ioflags & IO_ITEM)) return; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_SPECIAL_1].special = IO_SPECIAL_ELEM_NONE; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_SPECIAL_2].special = IO_SPECIAL_ELEM_NONE; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_SPECIAL_3].special = IO_SPECIAL_ELEM_NONE; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_SPECIAL_4].special = IO_SPECIAL_ELEM_NONE; } //*********************************************************************************************** // Sets an equipment property //----------------------------------------------------------------------------------------------- //*********************************************************************************************** float ARX_EQUIPMENT_Apply(INTERACTIVE_OBJ * io, long ident, float trueval) { if (io == NULL) return trueval; if (io != inter.iobj[0]) return trueval; float toadd = 0; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { INTERACTIVE_OBJ * toequip = inter.iobj[player.equiped[i]]; if ((toequip) && (toequip->ioflags & IO_ITEM) && (toequip->_itemdata->equipitem)) { IO_EQUIPITEM_ELEMENT * elem = &toequip->_itemdata->equipitem->elements[ident]; if (!(elem->flags & 1)) toadd += elem->value; } } } return toadd; } float ARX_EQUIPMENT_ApplyPercent(INTERACTIVE_OBJ * io, long ident, float trueval) { if (io == NULL) return trueval; if (io != inter.iobj[0]) return trueval; float toadd = 0; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { INTERACTIVE_OBJ * toequip = inter.iobj[player.equiped[i]]; if ((toequip) && (toequip->ioflags & IO_ITEM) && (toequip->_itemdata->equipitem)) { IO_EQUIPITEM_ELEMENT * elem = &toequip->_itemdata->equipitem->elements[ident]; if (elem->flags & 1) // percentile value... { toadd += elem->value; } } } } return (toadd * trueval * DIV100); } //*********************************************************************************************** //----------------------------------------------------------------------------------------------- //*********************************************************************************************** float ARX_EQUIPMENT_GetSpecialValue(INTERACTIVE_OBJ * io, long val) { if ((!io) || !(io->ioflags & IO_ITEM) || !io->_itemdata->equipitem) return -1; for (long i = IO_EQUIPITEM_ELEMENT_SPECIAL_1; i <= IO_EQUIPITEM_ELEMENT_SPECIAL_4; i++) { if (io->_itemdata->equipitem->elements[i].special == val) { return (io->_itemdata->equipitem->elements[i].value); } } return -1; } void ARX_EQUIPMENT_SetEquip(INTERACTIVE_OBJ * io, char * param1, char * param2, float val, short flags) { if (io == NULL) return; if (!(io->ioflags & IO_ITEM)) return; if (!io->_itemdata->equipitem) { io->_itemdata->equipitem = (IO_EQUIPITEM *) malloc(sizeof(IO_EQUIPITEM)); //"IOequip" if (io->_itemdata->equipitem == NULL) return; memset(io->_itemdata->equipitem, 0, sizeof(IO_EQUIPITEM)); io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Duration].value = 10; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_AimTime].value = 10; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Damages].value = 0; io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Identify_Value].value = 0; } if (!stricmp(param1, "-s")) { for (long i = IO_EQUIPITEM_ELEMENT_SPECIAL_1; i <= IO_EQUIPITEM_ELEMENT_SPECIAL_4; i++) { if (io->_itemdata->equipitem->elements[i].special == IO_SPECIAL_ELEM_NONE) { if (!stricmp(param2, "PARALYSE")) io->_itemdata->equipitem->elements[i].special = IO_SPECIAL_ELEM_PARALYZE; else if (!stricmp(param2, "DRAINLIFE")) io->_itemdata->equipitem->elements[i].special = IO_SPECIAL_ELEM_DRAIN_LIFE; io->_itemdata->equipitem->elements[i].value = val; io->_itemdata->equipitem->elements[i].flags = flags; return; } } return; } else for (long i = 0; i < IO_EQUIPITEM_ELEMENT_Number; i++) { if (!stricmp(param2, equipinfo[i].name)) { io->_itemdata->equipitem->elements[i].value = val; io->_itemdata->equipitem->elements[i].special = 0; io->_itemdata->equipitem->elements[i].flags = flags; return; } } } //----------------------------------------------------------------------------- void ARX_EQUIPMENT_IdentifyAll() { INTERACTIVE_OBJ * io = inter.iobj[0]; if (io == NULL) return; if (io != inter.iobj[0]) return; for (long i = 0; i < MAX_EQUIPED; i++) { if ((player.equiped[i] != 0) && ValidIONum(player.equiped[i])) { INTERACTIVE_OBJ * toequip = inter.iobj[player.equiped[i]]; if ((toequip) && (toequip->ioflags & IO_ITEM) && (toequip->_itemdata->equipitem)) { if (player.Full_Skill_Object_Knowledge + player.Full_Attribute_Mind >= toequip->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Identify_Value].value) { SendIOScriptEvent(toequip, SM_IDENTIFY, ""); } } } } } float GetHitValue(char * name) { long len = strlen(name); if (len < 5) return -1; if (((name[0] == 'H') || (name[0] == 'h')) && ((name[1] == 'I') || (name[1] == 'i')) && ((name[2] == 'T') || (name[1] == 't')) && (name[3] == '_')) { long val = atoi(name + 4); return (float)val; } return -1; }