void FlyingEyeSpell::Update() { const ArxInstant now = arxtime.now(); const ArxDuration framediff3 = now - m_lastupdate; eyeball.floating = std::sin(m_lastupdate - m_timcreation * 0.001f); eyeball.floating *= 10.f; if(m_lastupdate - m_timcreation <= ArxDurationMs(3000)) { eyeball.exist = m_lastupdate - m_timcreation * (1.0f / 30); eyeball.size = Vec3f(1.f - float(eyeball.exist) * 0.01f); eyeball.angle.setYaw(eyeball.angle.getYaw() + toMs(framediff3) * 0.6f); } else { eyeball.exist = 2; } m_lastupdate = now; Entity * io = entities.player(); if(io->obj->fastaccess.primary_attach != ActionPoint()) { Vec3f pos = actionPointPosition(io->obj, io->obj->fastaccess.primary_attach); FlyingEyeSpellUpdateHand(pos, m_light1); } if(io->obj->fastaccess.left_attach != ActionPoint()) { Vec3f pos = actionPointPosition(io->obj, io->obj->fastaccess.left_attach); FlyingEyeSpellUpdateHand(pos, m_light2); } }
static ActionPoint GetActionPoint(const EERIE_3DOBJ * obj, const char * name) { if(!obj) return ActionPoint(); BOOST_FOREACH(const EERIE_ACTIONLIST & act, obj->actionlist) { if(act.name == name) { return act.idx; } } return ActionPoint(); }
ActionPoint GetActionPointIdx(const EERIE_3DOBJ * eobj, const std::string & text) { if(!eobj) return ActionPoint(); BOOST_FOREACH(const EERIE_ACTIONLIST & action, eobj->actionlist) { if(action.name == text) { return action.idx; } } return ActionPoint(); }
void SpellBase::updateCasterHand() { // Create hand position if a hand is defined if(m_caster == EntityHandle_Player) { m_hand_group = entities[m_caster]->obj->fastaccess.primary_attach; } else { m_hand_group = entities[m_caster]->obj->fastaccess.left_attach; } if(m_hand_group != ActionPoint()) { m_hand_pos = actionPointPosition(entities[m_caster]->obj, m_hand_group); } }
static void ObjectAddAction(EERIE_3DOBJ * obj, const std::string & name, long act, long sfx, const EERIE_VERTEX * vert) { size_t newvert = ObjectAddVertex(obj, vert); for(std::vector<EERIE_ACTIONLIST>::iterator i = obj->actionlist.begin(); i != obj->actionlist.end(); ++i) { if(i->name == name) { return; } } obj->actionlist.push_back(EERIE_ACTIONLIST()); EERIE_ACTIONLIST & action = obj->actionlist.back(); action.name = name; action.act = act; action.sfx = sfx; action.idx = ActionPoint(newvert); }
static EERIE_3DOBJ * CreateIntermediaryMesh(const EERIE_3DOBJ * obj1, const EERIE_3DOBJ * obj2, long tw) { ObjSelection tw1 = ObjSelection(); ObjSelection tw2 = ObjSelection(); ObjSelection iw1 = ObjSelection(); ObjSelection jw1 = ObjSelection(); ObjSelection sel_head1 = ObjSelection(); ObjSelection sel_head2 = ObjSelection(); ObjSelection sel_torso1 = ObjSelection(); ObjSelection sel_torso2 = ObjSelection(); ObjSelection sel_legs1 = ObjSelection(); ObjSelection sel_legs2 = ObjSelection(); // First we retreive selection groups indexes for(size_t i = 0; i < obj1->selections.size(); i++) { // TODO iterator ObjSelection sel = ObjSelection(i); if(obj1->selections[i].name == "head") { sel_head1 = sel; } else if(obj1->selections[i].name == "chest") { sel_torso1 = sel; } else if(obj1->selections[i].name == "leggings") { sel_legs1 = sel; } } for(size_t i = 0; i < obj2->selections.size(); i++) { // TODO iterator ObjSelection sel = ObjSelection(i); if(obj2->selections[i].name == "head") { sel_head2 = sel; } else if(obj2->selections[i].name == "chest") { sel_torso2 = sel; } else if(obj2->selections[i].name == "leggings") { sel_legs2 = sel; } } if(sel_head1 == ObjSelection()) return NULL; if(sel_head2 == ObjSelection()) return NULL; if(sel_torso1 == ObjSelection()) return NULL; if(sel_torso2 == ObjSelection()) return NULL; if(sel_legs1 == ObjSelection()) return NULL; if(sel_legs2 == ObjSelection()) return NULL; if(tw == TWEAK_HEAD) { tw1 = sel_head1; tw2 = sel_head2; iw1 = sel_torso1; jw1 = sel_legs1; } if(tw == TWEAK_TORSO) { tw1 = sel_torso1; tw2 = sel_torso2; iw1 = sel_head1; jw1 = sel_legs1; } if(tw == TWEAK_LEGS) { tw1 = sel_legs1; tw2 = sel_legs2; iw1 = sel_torso1; jw1 = sel_head1; } if(tw1 == ObjSelection() || tw2 == ObjSelection()) return NULL; // Now Retreives Tweak Action Points { ActionPoint idx_head1 = GetActionPoint(obj1, "head2chest"); if(idx_head1 == ActionPoint()) return NULL; ActionPoint idx_head2 = GetActionPoint(obj2, "head2chest"); if(idx_head2 == ActionPoint()) return NULL; ActionPoint idx_torso1 = GetActionPoint(obj1, "chest2leggings"); if(idx_torso1 == ActionPoint()) return NULL; ActionPoint idx_torso2 = GetActionPoint(obj2, "chest2leggings"); if(idx_torso2 == ActionPoint()) return NULL; } // copy vertices std::vector<EERIE_VERTEX> obj1vertexlist2 = obj1->vertexlist; std::vector<EERIE_VERTEX> obj2vertexlist2 = obj2->vertexlist; // Work will contain the Tweaked object EERIE_3DOBJ * work = new EERIE_3DOBJ; work->pos = obj1->pos; work->angle = obj1->angle; // We reset all data to create a fresh object work->cub = obj1->cub; work->quat = obj1->quat; // Linked objects are linked to this object. if(obj1->linked.size() > obj2->linked.size()) { work->linked = obj1->linked; } else { work->linked = obj2->linked; } // Is the origin of object in obj1 or obj2 ? Retreives it for work object if(IsInSelection(obj1, obj1->origin, tw1)) { work->point0 = obj2->point0; work->origin = ObjectAddVertex(work, &obj2vertexlist2[obj2->origin]); } else { work->point0 = obj1->point0; work->origin = ObjectAddVertex(work, &obj1vertexlist2[obj1->origin]); } // Recreate Action Points included in work object.for Obj1 for(size_t i = 0; i < obj1->actionlist.size(); i++) { const EERIE_ACTIONLIST & action = obj1->actionlist[i]; if( IsInSelection(obj1, action.idx.handleData(), iw1) || IsInSelection(obj1, action.idx.handleData(), jw1) || action.name == "head2chest" || action.name == "chest2leggings" ) { ObjectAddAction(work, action.name, action.act, action.sfx, &obj1vertexlist2[action.idx.handleData()]); } } // Do the same for Obj2 for(size_t i = 0; i < obj2->actionlist.size(); i++) { const EERIE_ACTIONLIST & action = obj2->actionlist[i]; if( IsInSelection(obj2, action.idx.handleData(), tw2) || action.name == "head2chest" || action.name == "chest2leggings" ) { ObjectAddAction(work, action.name, action.act, action.sfx, &obj2vertexlist2[action.idx.handleData()]); } } // Recreate Vertex using Obj1 Vertexes for(size_t i = 0; i < obj1->vertexlist.size(); i++) { if(IsInSelection(obj1, i, iw1) || IsInSelection(obj1, i, jw1)) { ObjectAddVertex(work, &obj1vertexlist2[i]); } } // The same for Obj2 for(size_t i = 0; i < obj2->vertexlist.size(); i++) { if(IsInSelection(obj2, i, tw2)) { ObjectAddVertex(work, &obj2vertexlist2[i]); } } // Look in Faces for forgotten Vertexes... AND // Re-Create TextureContainers Infos // We look for texturecontainers included in the future tweaked object TextureContainer * tc = NULL; for(size_t i = 0; i < obj1->facelist.size(); i++) { const EERIE_FACE & face = obj1->facelist[i]; if( (IsInSelection(obj1, face.vid[0], iw1) || IsInSelection(obj1, face.vid[0], jw1)) && (IsInSelection(obj1, face.vid[1], iw1) || IsInSelection(obj1, face.vid[1], jw1)) && (IsInSelection(obj1, face.vid[2], iw1) || IsInSelection(obj1, face.vid[2], jw1)) ) { if(face.texid != -1) { if(tc != obj1->texturecontainer[face.texid]) { tc = obj1->texturecontainer[face.texid]; ObjectAddMap(work, tc); } } ObjectAddFace(work, &face, obj1); } } for(size_t i = 0; i < obj2->facelist.size(); i++) { const EERIE_FACE & face = obj2->facelist[i]; if( IsInSelection(obj2, face.vid[0], tw2) || IsInSelection(obj2, face.vid[1], tw2) || IsInSelection(obj2, face.vid[2], tw2) ) { if(face.texid != -1) { if(tc != obj2->texturecontainer[face.texid]) { tc = obj2->texturecontainer[face.texid]; ObjectAddMap(work, tc); } } ObjectAddFace(work, &face, obj2); } } // Recreate Groups work->grouplist.resize(std::max(obj1->grouplist.size(), obj2->grouplist.size())); for(size_t k = 0; k < obj1->grouplist.size(); k++) { const VertexGroup & grp = obj1->grouplist[k]; work->grouplist[k].name = grp.name; long v = GetEquivalentVertex(work, &obj1vertexlist2[grp.origin]); if(v >= 0) { work->grouplist[k].siz = grp.siz; if(IsInSelection(obj1, grp.origin, iw1) || IsInSelection(obj1, grp.origin, jw1)) work->grouplist[k].origin = v; } } for(size_t k = 0; k < obj2->grouplist.size(); k++) { if(k >= obj1->grouplist.size()) { work->grouplist[k].name = obj2->grouplist[k].name; } long v = GetEquivalentVertex(work, &obj2vertexlist2[obj2->grouplist[k].origin]); if(v >= 0) { work->grouplist[k].siz = obj2->grouplist[k].siz; if(IsInSelection(obj2, obj2->grouplist[k].origin, tw2)) work->grouplist[k].origin = v; } } // Recreate Selection Groups (only the 3 selections needed to reiterate MeshTweaking !) work->selections.resize(3); work->selections[0].name = "head"; work->selections[1].name = "chest"; work->selections[2].name = "leggings"; // Re-Creating sel_head if(tw == TWEAK_HEAD) { const EERIE_SELECTIONS & sel = obj2->selections[sel_head2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 0, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_head1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 0, t); } } } // Re-Create sel_torso if(tw == TWEAK_TORSO) { const EERIE_SELECTIONS & sel = obj2->selections[sel_torso2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 1, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_torso1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 1, t); } } } // Re-Create sel_legs if(tw == TWEAK_LEGS) { const EERIE_SELECTIONS & sel = obj2->selections[sel_legs2.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 2, t); } } } else { const EERIE_SELECTIONS & sel = obj1->selections[sel_legs1.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, 2, t); } } } //Now recreates other selections... for(size_t i = 0; i < obj1->selections.size(); i++) { if(EERIE_OBJECT_GetSelection(work, obj1->selections[i].name) == ObjSelection()) { size_t num = work->selections.size(); work->selections.resize(num + 1); work->selections[num].name = obj1->selections[i].name; for(size_t l = 0; l < obj1->selections[i].selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj1vertexlist2[obj1->selections[i].selected[l]].v; long t = GetEquivalentVertex(work, &temp); if (t != -1) { ObjectAddSelection(work, num, t); } } ObjSelection ii = EERIE_OBJECT_GetSelection(obj2, obj1->selections[i].name); if(ii != ObjSelection()) { const EERIE_SELECTIONS & sel = obj2->selections[ii.handleData()]; for(size_t l = 0; l < sel.selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[sel.selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, num, t); } } } } } for(size_t i = 0; i < obj2->selections.size(); i++) { if(EERIE_OBJECT_GetSelection(work, obj2->selections[i].name) == ObjSelection()) { size_t num = work->selections.size(); work->selections.resize(num + 1); work->selections[num].name = obj2->selections[i].name; for(size_t l = 0; l < obj2->selections[i].selected.size(); l++) { EERIE_VERTEX temp; temp.v = obj2vertexlist2[obj2->selections[i].selected[l]].v; long t = GetEquivalentVertex(work, &temp); if(t != -1) { ObjectAddSelection(work, num, t); } } } } // Recreate Animation-groups vertex for(size_t i = 0; i < obj1->grouplist.size(); i++) { for(size_t j = 0; j < obj1->grouplist[i].indexes.size(); j++) { AddVertexToGroup(work, i, &obj1vertexlist2[obj1->grouplist[i].indexes[j]]); } } for(size_t i = 0; i < obj2->grouplist.size(); i++) { for(size_t j = 0; j < obj2->grouplist[i].indexes.size(); j++) { AddVertexToGroup(work, i, &obj2vertexlist2[obj2->grouplist[i].indexes[j]]); } } work->vertexWorldPositions.resize(work->vertexlist.size()); work->vertexClipPositions.resize(work->vertexlist.size()); work->vertexColors.resize(work->vertexlist.size()); return work; }
void FlyingEyeSpell::Update(float timeDelta) { ARX_UNUSED(timeDelta); const unsigned long tim = (unsigned long)(arxtime); const long framediff3 = tim - m_lastupdate; eyeball.floating = std::sin(m_lastupdate-m_timcreation * 0.001f); eyeball.floating *= 10.f; if(m_lastupdate-m_timcreation <= 3000) { eyeball.exist = m_lastupdate - m_timcreation * (1.0f / 30); eyeball.size = Vec3f(1.f - float(eyeball.exist) * 0.01f); eyeball.angle.setPitch(eyeball.angle.getPitch() + framediff3 * 0.6f); } else { eyeball.exist = 2; } m_lastupdate=tim; Entity * io = entities.player(); EERIE_3DOBJ * eobj = io->obj; long pouet = 2; while(pouet) { ActionPoint id; if(pouet == 2) id = io->obj->fastaccess.primary_attach; else id = GetActionPointIdx(io->obj, "left_attach"); pouet--; if(id != ActionPoint()) { if(!lightHandleIsValid(special[pouet])) { special[pouet] = GetFreeDynLight(); } if(lightHandleIsValid(special[pouet])) { EERIE_LIGHT * el = lightHandleGet(special[pouet]); el->intensity = 1.3f; el->fallend = 180.f; el->fallstart = 50.f; el->rgb = Color3f(0.7f, 0.3f, 1.f); el->pos = actionPointPosition(eobj, id); } for(long kk = 0; kk < 2; kk++) { PARTICLE_DEF * pd = createParticle(); if(!pd) { break; } pd->ov = actionPointPosition(eobj, id) + randomVec(-1.f, 1.f); pd->move = Vec3f(0.1f, 0.f, 0.1f) + Vec3f(-0.2f, -2.2f, -0.2f) * randomVec3f(); pd->siz = 5.f; pd->tolive = Random::get(1500, 3500); pd->scale = Vec3f(0.2f); pd->tc = TC_smoke; pd->special = FADE_IN_AND_OUT | ROTATING | MODULATE_ROTATION | DISSIPATING; pd->sourceionum = PlayerEntityHandle; pd->source = &eobj->vertexlist3[id.handleData()].v; // FIXME passing of pointer to vertex position pd->fparam = 0.0000001f; pd->rgb = Color3f(.7f, .3f, 1.f) + Color3f(-.1f, -.1f, -.1f) * randomColor3f(); } } } }
void DouseSpell::Launch() { m_duration = ArxDurationMs(500); Vec3f target; if(m_hand_group != ActionPoint()) { target = m_hand_pos; } else { target = m_caster_pos; target.y -= 50.f; } float fPerimeter = 400.f + m_level * 30.f; CheckForIgnition(Sphere(target, fPerimeter), 0, 1); for(size_t ii = 0; ii < g_staticLightsMax; ii++) { EERIE_LIGHT * light = g_staticLights[ii]; if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) { continue; } if(!(light->extras & EXTRAS_SEMIDYNAMIC) && !(light->extras & EXTRAS_SPAWNFIRE) && !(light->extras & EXTRAS_SPAWNSMOKE)) { continue; } if(!light->m_ignitionStatus) { continue; } if(!fartherThan(target, light->pos, fPerimeter)) { m_lights.push_back(ii); } } if(player.torch && closerThan(target, player.pos, fPerimeter)) { ARX_PLAYER_ClickedOnTorch(player.torch); } for(size_t k = 0; k < MAX_SPELLS; k++) { SpellBase * spell = spells[SpellHandle(k)]; if(!spell) { continue; } switch(spell->m_type) { case SPELL_FIREBALL: { Vec3f pos = spell->getPosition(); float radius = std::max(m_level * 2.f, 12.f); if(closerThan(target, pos, fPerimeter + radius)) { spell->m_level -= m_level; if(spell->m_level < 1) { spells.endSpell(spell); } } break; } case SPELL_FIRE_FIELD: { Vec3f pos = spell->getPosition(); if(closerThan(target, pos, fPerimeter + 200)) { spell->m_level -= m_level; if(spell->m_level < 1) { spells.endSpell(spell); } } break; } default: break; } } }
void IgnitSpell::Launch() { m_duration = ArxDurationMs(500); if(m_hand_group != ActionPoint()) { m_srcPos = m_hand_pos; } else { m_srcPos = m_caster_pos - Vec3f(0.f, 50.f, 0.f); } EERIE_LIGHT * light = dynLightCreate(); if(light) { light->intensity = 1.8f; light->fallend = 450.f; light->fallstart = 380.f; light->rgb = Color3f(1.f, 0.75f, 0.5f); light->pos = m_srcPos; light->duration = ArxDurationMs(300); } float fPerimeter = 400.f + m_level * 30.f; m_lights.clear(); m_elapsed = ArxDuration_ZERO; CheckForIgnition(Sphere(m_srcPos, fPerimeter), 1, 1); for(size_t ii = 0; ii < g_staticLightsMax; ii++) { EERIE_LIGHT * light = g_staticLights[ii]; if(!light || !(light->extras & EXTRAS_EXTINGUISHABLE)) { continue; } if(m_caster == EntityHandle_Player && (light->extras & EXTRAS_NO_IGNIT)) { continue; } if(!(light->extras & EXTRAS_SEMIDYNAMIC) && !(light->extras & EXTRAS_SPAWNFIRE) && !(light->extras & EXTRAS_SPAWNSMOKE)) { continue; } if(light->m_ignitionStatus) { continue; } if(!fartherThan(m_srcPos, light->pos, fPerimeter)) { T_LINKLIGHTTOFX entry; entry.m_targetLight = ii; EERIE_LIGHT * light = dynLightCreate(entry.m_effectLight); if(light) { light->intensity = Random::getf(0.7f, 2.7f); light->fallend = 400.f; light->fallstart = 300.f; light->rgb = Color3f(1.f, 1.f, 1.f); light->pos = light->pos; } m_lights.push_back(entry); } } for(size_t n = 0; n < MAX_SPELLS; n++) { SpellBase * spell = spells[SpellHandle(n)]; if(!spell) { continue; } if(spell->m_type == SPELL_FIREBALL) { Vec3f pos = static_cast<FireballSpell *>(spell)->getPosition(); float radius = std::max(m_level * 2.f, 12.f); if(closerThan(m_srcPos, pos, fPerimeter + radius)) { spell->m_level += 1; } } } }
void MagicMissileSpell::Launch() { m_duration = ArxDurationMs(6000); m_hand_group = GetActionPointIdx(entities[m_caster]->obj, "primary_attach"); if(m_hand_group != ActionPoint()) { Entity * caster = entities[m_caster]; ActionPoint group = m_hand_group; m_hand_pos = actionPointPosition(caster->obj, group); } Vec3f startPos; float pitch, yaw; if(m_caster == EntityHandle_Player) { yaw = player.angle.getYaw(); pitch = player.angle.getPitch(); Vec3f vector = angleToVector(Anglef(pitch, yaw, 0.f)) * 60.f; if(m_hand_group != ActionPoint()) { startPos = m_hand_pos; } else { startPos = player.pos; startPos += angleToVectorXZ(yaw); } startPos += vector; } else { pitch = 0; yaw = entities[m_caster]->angle.getYaw(); Vec3f vector = angleToVector(Anglef(pitch, yaw, 0.f)) * 60.f; if(m_hand_group != ActionPoint()) { startPos = m_hand_pos; } else { startPos = entities[m_caster]->pos; } startPos += vector; Entity * io = entities[m_caster]; if(ValidIONum(io->targetinfo)) { const Vec3f & p1 = m_caster_pos; const Vec3f & p2 = entities[io->targetinfo]->pos; pitch = -(glm::degrees(getAngle(p1.y, p1.z, p2.y, p2.z + glm::distance(Vec2f(p2.x, p2.z), Vec2f(p1.x, p1.z))))); //alpha entre orgn et dest; } else if (ValidIONum(m_target)) { const Vec3f & p1 = m_caster_pos; const Vec3f & p2 = entities[m_target]->pos; pitch = -(glm::degrees(getAngle(p1.y, p1.z, p2.y, p2.z + glm::distance(Vec2f(p2.x, p2.z), Vec2f(p1.x, p1.z))))); //alpha entre orgn et dest; } } m_mrCheat = (m_caster == EntityHandle_Player && cur_mr == 3); ArxDuration lMax = ArxDuration_ZERO; long number; if(sp_max || cur_rf == 3) { number = long(m_level); } else { number = glm::clamp(long(m_level + 1) / 2, 1l, 5l); } pTab.reserve(number); for(size_t i = 0; i < size_t(number); i++) { CMagicMissile * missile = NULL; if(!m_mrCheat) { missile = new CMagicMissile(); } else { missile = new MrMagicMissileFx(); } pTab.push_back(missile); Anglef angles(pitch, yaw, 0.f); if(i > 0) { angles.setPitch(angles.getPitch() + Random::getf(-4.0f, 4.0f)); angles.setYaw(angles.getYaw() + Random::getf(-6.0f, 6.0f)); } missile->Create(startPos, angles); ArxDuration lTime = m_duration + ArxDurationMs(Random::get(-1000, 1000)); lTime = std::max(ArxDurationMs(1000), lTime); lMax = std::max(lMax, lTime); missile->SetDuration(lTime); EERIE_LIGHT * el = dynLightCreate(missile->lLightId); if(el) { el->intensity = 0.7f + 2.3f; el->fallend = 190.f; el->fallstart = 80.f; if(m_mrCheat) { el->rgb = Color3f(1.f, 0.3f, 0.8f); } else { el->rgb = Color3f(0.f, 0.f, 1.f); } el->pos = startPos; el->duration = ArxDurationMs(300); } } m_duration = lMax + ArxDurationMs(1000); }
static void loadObjectData(EERIE_3DOBJ * eerie, const char * adr, size_t * poss, long version) { LogWarning << "loadObjectData"; size_t pos = *poss; const THEO_OFFSETS * to = reinterpret_cast<const THEO_OFFSETS *>(adr + pos); pos += sizeof(THEO_OFFSETS); const THEO_NB * tn = reinterpret_cast<const THEO_NB *>(adr + pos); LogDebug("Nb Vertex " << tn->nb_vertex << " Nb Action Points " << tn->nb_action_point << " Nb Lines " << tn->nb_lines); LogDebug("Nb Faces " << tn->nb_faces << " Nb Groups " << tn->nb_groups); eerie->vertexlist.resize(tn->nb_vertex); eerie->vertexlist3.resize(tn->nb_vertex); eerie->facelist.resize(tn->nb_faces); eerie->grouplist.resize(tn->nb_groups); eerie->actionlist.resize(tn->nb_action_point); eerie->ndata = NULL; eerie->pdata = NULL; eerie->cdata = NULL; eerie->sdata = NULL; // read vertices pos = to->vertex_seek; if(tn->nb_vertex > 65535) { LogError << ("Warning Vertex Number Too High..."); } for(long i = 0; i < tn->nb_vertex; i++) { const THEO_VERTEX * ptv = reinterpret_cast<const THEO_VERTEX *>(adr + pos); pos += sizeof(THEO_VERTEX); eerie->vertexlist[i].v = ptv->pos.toVec3(); eerie->cub.xmin = std::min(eerie->cub.xmin, ptv->pos.x); eerie->cub.xmax = std::max(eerie->cub.xmax, ptv->pos.x); eerie->cub.ymin = std::min(eerie->cub.ymin, ptv->pos.y); eerie->cub.ymax = std::max(eerie->cub.ymax, ptv->pos.y); eerie->cub.zmin = std::min(eerie->cub.zmin, ptv->pos.z); eerie->cub.zmax = std::max(eerie->cub.zmax, ptv->pos.z); } // Lecture des FACES THEO pos = to->faces_seek; for(size_t i = 0; i < size_t(tn->nb_faces); i++) { THEO_FACES_3006 tf3006; const THEO_FACES_3006 * ptf3006; if(version >= 3006) { ptf3006 = reinterpret_cast<const THEO_FACES_3006 *>(adr + pos); pos += sizeof(THEO_FACES_3006); } else { memset(&tf3006, 0, sizeof(THEO_FACES_3006)); const THEO_FACES * ptf = reinterpret_cast<const THEO_FACES *>(adr + pos); pos += sizeof(THEO_FACES); tf3006.color = ptf->color; tf3006.index1 = ptf->index1; tf3006.index2 = ptf->index2; tf3006.index3 = ptf->index3; tf3006.ismap = ptf->ismap; tf3006.liste_uv = ptf->liste_uv; tf3006.element_uv = ptf->element_uv; tf3006.num_map = ptf->num_map; tf3006.tile_x = ptf->tile_x; tf3006.tile_y = ptf->tile_y; tf3006.user_tile_x = ptf->user_tile_x; tf3006.user_tile_y = ptf->user_tile_y; tf3006.flag = ptf->flag; tf3006.collision_type = ptf->collision_type; tf3006.rgb = ptf->rgb; tf3006.rgb1 = ptf->rgb1; tf3006.rgb2 = ptf->rgb2; tf3006.rgb3 = ptf->rgb3; tf3006.double_side = ptf->double_side; tf3006.transparency = ptf->transparency; tf3006.trans = ptf->trans; ptf3006 = &tf3006; } eerie->facelist[i].vid[0] = (unsigned short)ptf3006->index1; eerie->facelist[i].vid[1] = (unsigned short)ptf3006->index2; eerie->facelist[i].vid[2] = (unsigned short)ptf3006->index3; s32 num_map = ((size_t)ptf3006->num_map >= eerie->texturecontainer.size()) ? -1 : ptf3006->num_map; if(ptf3006->ismap) { eerie->facelist[i].texid = (short)num_map; eerie->facelist[i].facetype = POLY_NO_SHADOW; if(num_map >= 0 && eerie->texturecontainer[num_map] && (eerie->texturecontainer[num_map]->userflags & POLY_NOCOL)) { eerie->facelist[i].facetype |= POLY_NOCOL; } } else { eerie->facelist[i].texid = -1; } switch(ptf3006->flag) { case 0: eerie->facelist[i].facetype |= POLY_GLOW; break; case 1: eerie->facelist[i].facetype |= POLY_NO_SHADOW; break; case 4: eerie->facelist[i].facetype |= POLY_METAL; break; case 10: eerie->facelist[i].facetype |= POLY_NOPATH; break; case 11: eerie->facelist[i].facetype |= POLY_CLIMB; break; case 12: eerie->facelist[i].facetype |= POLY_NOCOL; break; case 13: eerie->facelist[i].facetype |= POLY_NODRAW; break; case 14: eerie->facelist[i].facetype |= POLY_PRECISE_PATH; break; case 16: eerie->facelist[i].facetype |= POLY_NO_CLIMB; break; } eerie->facelist[i].ou[0] = (short)ptf3006->liste_uv.u1; eerie->facelist[i].ov[0] = (short)ptf3006->liste_uv.v1; eerie->facelist[i].ou[1] = (short)ptf3006->liste_uv.u2; eerie->facelist[i].ov[1] = (short)ptf3006->liste_uv.v2; eerie->facelist[i].ou[2] = (short)ptf3006->liste_uv.u3; eerie->facelist[i].ov[2] = (short)ptf3006->liste_uv.v3; if(ptf3006->double_side) { eerie->facelist[i].facetype |= POLY_DOUBLESIDED; } if(ptf3006->transparency > 0) { if(ptf3006->transparency == 2) { // NORMAL TRANS 0.00001 to 0.999999 if(ptf3006->trans < 1.f) { eerie->facelist[i].facetype |= POLY_TRANS; eerie->facelist[i].transval = ptf3006->trans; } } else if (ptf3006->transparency == 1) { if(ptf3006->trans < 0.f) { // SUBTRACTIVE -0.000001 to -0.999999 eerie->facelist[i].facetype |= POLY_TRANS; eerie->facelist[i].transval = ptf3006->trans; } else { // ADDITIVE 1.000001 to 1.9999999 eerie->facelist[i].facetype |= POLY_TRANS; eerie->facelist[i].transval = ptf3006->trans + 1.f; } } else { // MULTIPLICATIVE 2.000001 to 2.9999999 eerie->facelist[i].facetype |= POLY_TRANS; eerie->facelist[i].transval = ptf3006->trans + 2.f; } } if(eerie->facelist[i].texid != -1 && !eerie->texturecontainer.empty() && eerie->texturecontainer[eerie->facelist[i].texid] != NULL) { if(eerie->texturecontainer[eerie->facelist[i].texid]->userflags & POLY_TRANS) { if(!(eerie->facelist[i].facetype & POLY_TRANS)) { eerie->facelist[i].facetype |= POLY_TRANS; eerie->facelist[i].transval = ptf3006->trans; } } if(eerie->texturecontainer[eerie->facelist[i].texid]->userflags & POLY_WATER) { eerie->facelist[i].facetype |= POLY_WATER; } if(eerie->texturecontainer[eerie->facelist[i].texid]->userflags & POLY_LAVA) { eerie->facelist[i].facetype |= POLY_LAVA; } if(eerie->texturecontainer[eerie->facelist[i].texid]->userflags & POLY_FALL) { eerie->facelist[i].facetype |= POLY_FALL; } if(eerie->texturecontainer[eerie->facelist[i].texid]->userflags & POLY_CLIMB) { eerie->facelist[i].facetype |= POLY_CLIMB; } } } // Groups Data pos = to->groups_seek; for(long i = 0; i < tn->nb_groups; i++) { THEO_GROUPS_3011 tg3011; const THEO_GROUPS_3011 * ptg3011; if(version >= 3011) { ptg3011 = reinterpret_cast<const THEO_GROUPS_3011 *>(adr + pos); pos += sizeof(THEO_GROUPS_3011); } else { const THEO_GROUPS * ltg = reinterpret_cast<const THEO_GROUPS *>(adr + pos); pos += sizeof(THEO_GROUPS); memset(&tg3011, 0, sizeof(THEO_GROUPS_3011)); tg3011.origin = ltg->origin; tg3011.nb_index = ltg->nb_index; ptg3011 = &tg3011; } eerie->grouplist[i].origin = ptg3011->origin; eerie->grouplist[i].indexes.resize(ptg3011->nb_index); std::copy((const long*)(adr + pos), (const long*)(adr + pos) + ptg3011->nb_index, eerie->grouplist[i].indexes.begin()); pos += ptg3011->nb_index * sizeof(long); eerie->grouplist[i].name = boost::to_lower_copy(util::loadString(adr + pos, 256)); pos += 256; eerie->grouplist[i].siz = 0.f; for(long o = 0; o < ptg3011->nb_index; o++) { eerie->grouplist[i].siz = std::max(eerie->grouplist[i].siz, fdist(eerie->vertexlist[eerie->grouplist[i].origin].v, eerie->vertexlist[eerie->grouplist[i].indexes[o]].v)); } eerie->grouplist[i].siz = ffsqrt(eerie->grouplist[i].siz) * (1.f/16); } // SELECTIONS s32 THEO_nb_selected = *reinterpret_cast<const s32 *>(adr + pos); pos += sizeof(s32); eerie->selections.resize(THEO_nb_selected); for(long i = 0; i < THEO_nb_selected; i++) { const THEO_SELECTED * pts = reinterpret_cast<const THEO_SELECTED *>(adr + pos); pos += sizeof(THEO_SELECTED); eerie->selections[i].name = boost::to_lower_copy(util::loadString(pts->name)); eerie->selections[i].selected.resize(pts->nb_index); if(pts->nb_index > 0) { std::copy((const long*)(adr + pos), (const long*)(adr + pos) + pts->nb_index, eerie->selections[i].selected.begin()); pos += sizeof(long) * pts->nb_index; } } // Theo Action Points Read pos = to->action_point_seek; for(long i = 0; i < tn->nb_action_point; i++) { const THEO_ACTION_POINT * ptap = reinterpret_cast<const THEO_ACTION_POINT *>(adr + pos); pos += sizeof(THEO_ACTION_POINT); eerie->actionlist[i].act = ptap->action; eerie->actionlist[i].sfx = ptap->num_sfx; eerie->actionlist[i].idx = ActionPoint(ptap->vert_index); eerie->actionlist[i].name = boost::to_lower_copy(util::loadString(ptap->name)); } eerie->angle = Anglef::ZERO; eerie->pos = Vec3f_ZERO; // Now Interpret Extra Data chunk pos = to->extras_seek + 4; if(version >= 3005) { const THEO_EXTRA_DATA_3005 * pted3005 = reinterpret_cast<const THEO_EXTRA_DATA_3005 *>(adr + pos); pos += sizeof(THEO_EXTRA_DATA_3005); eerie->pos = pted3005->pos.toVec3(); eerie->angle.setYaw((float)(pted3005->angle.alpha & 0xfff) * THEO_ROTCONVERT); eerie->angle.setPitch((float)(pted3005->angle.beta & 0xfff) * THEO_ROTCONVERT); eerie->angle.setRoll((float)(pted3005->angle.gamma & 0xfff) * THEO_ROTCONVERT); eerie->point0 = eerie->vertexlist[pted3005->origin_index].v; eerie->origin = pted3005->origin_index; eerie->quat = pted3005->quat; } else { const THEO_EXTRA_DATA * pted = reinterpret_cast<const THEO_EXTRA_DATA *>(adr + pos); pos += sizeof(THEO_EXTRA_DATA); eerie->pos = pted->pos.toVec3(); eerie->angle.setYaw((float)(pted->angle.alpha & 0xfff) * THEO_ROTCONVERT); eerie->angle.setPitch((float)(pted->angle.beta & 0xfff) * THEO_ROTCONVERT); eerie->angle.setRoll((float)(pted->angle.gamma & 0xfff) * THEO_ROTCONVERT); eerie->point0 = eerie->vertexlist[pted->origin_index].v; eerie->origin = pted->origin_index; } *poss = pos; eerie->vertexlist3 = eerie->vertexlist; ReCreateUVs(eerie); EERIE_Object_Precompute_Fast_Access(eerie); }
void ManageCombatModeAnimations() { arx_assert(entities.player()); if(player.m_aimTime > 0) { player.m_aimTime += g_platformTime.lastFrameDuration(); } Entity * const io = entities.player(); AnimLayer & layer1 = io->animlayer[1]; ANIM_HANDLE ** alist = io->anims; WeaponType weapontype = ARX_EQUIPMENT_GetPlayerWeaponType(); if(weapontype == WEAPON_BARE && LAST_WEAPON_TYPE != weapontype) { if(layer1.cur_anim != alist[ANIM_BARE_WAIT]) { changeAnimation(io, 1, alist[ANIM_BARE_WAIT]); player.m_aimTime = 0; } } switch(weapontype) { case WEAPON_BARE: { // BARE HANDS PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_BARE_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_BARE_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "bare"); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); // TODO inband signaling AnimationDuration player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT + j * 3]) { if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_BARE_WAIT], EA_LOOP); player.m_strikeDirection = 0; player.m_aimTime = PlatformDuration::ofRaw(1); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } else if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.2f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.8f && player.m_weaponBlocked == AnimationDuration::ofRaw(-1)) { ActionPoint id = ActionPoint(); if(layer1.cur_anim == alist[ANIM_BARE_STRIKE_LEFT]) { id = io->obj->fastaccess.left_attach; } else { // Strike Right id = io->obj->fastaccess.primary_attach; } if(id != ActionPoint()) { Sphere sphere; sphere.origin = actionPointPosition(io->obj, id); sphere.radius = 25.f; EntityHandle num; if(CheckAnythingInSphere(sphere, EntityHandle_Player, 0, &num)) { float dmgs = (player.m_miscFull.damages + 1) * player.m_strikeAimRatio; if(ARX_DAMAGES_TryToDoDamage(actionPointPosition(io->obj, id), dmgs, 40, EntityHandle_Player)) { player.m_weaponBlocked = layer1.ctime; } ParticleSparkSpawnContinous(sphere.origin, unsigned(dmgs), SpawnSparkType_Success); if(ValidIONum(num)) { static PlatformInstant lastHit = 0; PlatformInstant now = g_platformTime.frameStart(); if(now - lastHit > toPlatformDuration(layer1.ctime)) { ARX_SOUND_PlayCollision(entities[num]->material, MATERIAL_FLESH, 1.f, 1.f, sphere.origin, NULL); lastHit = now; } } } } } } } break; } case WEAPON_DAGGER: { // DAGGER PLAYER MANAGEMENT // Waiting and receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_DAGGER_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "dagger"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_DAGGER_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_DAGGER_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = PlatformDuration::ofRaw(1); player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_1H: { // 1HANDED PLAYER MANAGEMENT // Waiting and Received Strike Impulse if(layer1.cur_anim == alist[ANIM_1H_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_1H_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "1h"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_1H_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_1H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_2H: { // 2HANDED PLAYER MANAGEMENT // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_2H_WAIT]) { player.m_aimTime = 0; if(eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_START + player.m_strikeDirection * 3]); io->isHit = false; } } // Now go for strike cycle... for(long j = 0; j < 4; j++) { if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_START + j * 3] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT_CYCLE + j * 3] && !eeMousePressed1()) { changeAnimation(io, 1, alist[ANIM_2H_STRIKE_LEFT + j * 3]); strikeSpeak(io); SendIOScriptEvent(NULL, io, SM_STRIKE, "2h"); player.m_strikeDirection = 0; player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_2H_STRIKE_LEFT + j * 3]) { if( layer1.ctime > layer1.currentAltAnim()->anim_time * 0.3f && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.7f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; if(player.m_weaponBlocked == AnimationDuration::ofRaw(-1) && ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 0)) { player.m_weaponBlocked = layer1.ctime; } } if(layer1.flags & EA_ANIMEND) { changeAnimation(io, 1, alist[ANIM_2H_WAIT], EA_LOOP); layer1.flags &= ~(EA_PAUSED | EA_REVERSE); player.m_strikeDirection = 0; player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); } if( player.m_weaponBlocked != AnimationDuration::ofRaw(-1) && layer1.ctime < layer1.currentAltAnim()->anim_time * 0.9f ) { Entity * weapon = entities[player.equiped[EQUIP_SLOT_WEAPON]]; ARX_EQUIPMENT_Strike_Check(io, weapon, player.m_strikeAimRatio, 1); } } } break; } case WEAPON_BOW: { // MISSILE PLAYER MANAGEMENT if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE]) { player.m_bowAimRatio += bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration())); if(player.m_bowAimRatio > 1.f) player.m_bowAimRatio = 1.f; } // Waiting and Receiving Strike Impulse if(layer1.cur_anim == alist[ANIM_MISSILE_WAIT]) { player.m_aimTime = PlatformDuration::ofRaw(1); if(eeMousePressed1() && Player_Arrow_Count() > 0) { changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_1]); io->isHit = false; } } if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_1] && (layer1.flags & EA_ANIMEND)) { player.m_aimTime = 0; changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_PART_2]); EERIE_LINKEDOBJ_LinkObjectToObject(io->obj, arrowobj, "left_attach", "attach", NULL); } // Now go for strike cycle... if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_PART_2] && (layer1.flags & EA_ANIMEND)) { changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE_CYCLE], EA_LOOP); player.m_aimTime = PlatformDuration::ofRaw(1); } else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE_CYCLE] && !eeMousePressed1()) { EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); changeAnimation(io, 1, alist[ANIM_MISSILE_STRIKE]); SendIOScriptEvent(NULL, io, SM_STRIKE, "bow"); StrikeAimtime(); player.m_strikeAimRatio = player.m_bowAimRatio; Entity * quiver = Player_Arrow_Count_Decrease(); float poisonous = 0.f; if(quiver) { poisonous = quiver->poisonous; if(quiver->poisonous_count > 0) { quiver->poisonous_count--; if(quiver->poisonous_count <= 0) quiver->poisonous = 0; } ARX_DAMAGES_DurabilityLoss(quiver, 1.f); // TODO is this needed ?, quivers seem to self destruct via script, but maybe not all if(ValidIOAddress(quiver) && quiver->durability <= 0.f) { ARX_INTERACTIVE_DestroyIOdelayed(quiver); } } float aimratio = player.m_strikeAimRatio; if(sp_max && poisonous < 3.f) poisonous = 3.f; Vec3f orgPos = player.pos + Vec3f(0.f, 40.f, 0.f); if(io->obj->fastaccess.left_attach != ActionPoint()) { orgPos = actionPointPosition(io->obj, io->obj->fastaccess.left_attach); } Anglef orgAngle = player.angle; PlayerLaunchArrow_Test(aimratio, poisonous, orgPos, orgAngle); if(sp_max) { Anglef angle; Vec3f pos = player.pos + Vec3f(0.f, 40.f, 0.f); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() + 8); angle.setRoll(player.angle.getRoll()); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() - 8); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() + 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); angle.setPitch(player.angle.getPitch()); angle.setYaw(player.angle.getYaw() - 4.f); PlayerLaunchArrow_Test(aimratio, poisonous, pos, angle); } player.m_aimTime = 0; } else if(layer1.cur_anim == alist[ANIM_MISSILE_STRIKE]) { player.m_bowAimRatio -= bowZoomFromDuration(toMs(g_platformTime.lastFrameDuration())); if(player.m_bowAimRatio < 0) player.m_bowAimRatio = 0; if(layer1.flags & EA_ANIMEND) { player.m_bowAimRatio = 0; changeAnimation(io, 1, alist[ANIM_MISSILE_WAIT], EA_LOOP); player.m_aimTime = 0; player.m_weaponBlocked = AnimationDuration::ofRaw(-1); EERIE_LINKEDOBJ_UnLinkObjectFromObject(io->obj, arrowobj); } } break; } } LAST_WEAPON_TYPE = weapontype; }
void PoisonProjectileSpell::Launch() { ARX_SOUND_PlaySFX(g_snd.SPELL_POISON_PROJECTILE_LAUNCH, &m_caster_pos); Vec3f srcPos(0.f); float afBeta = 0.f; Entity * caster = entities[m_caster]; m_hand_group = caster->obj->fastaccess.primary_attach; if(m_hand_group != ActionPoint()) { ActionPoint group = m_hand_group; m_hand_pos = actionPointPosition(caster->obj, group); } if(m_caster == EntityHandle_Player) { afBeta = player.angle.getYaw(); if(m_hand_group != ActionPoint()) { srcPos = m_hand_pos; } else { srcPos = player.pos; } } else { afBeta = entities[m_caster]->angle.getYaw(); if(m_hand_group != ActionPoint()) { srcPos = m_hand_pos; } else { srcPos = entities[m_caster]->pos; } } srcPos += angleToVectorXZ(afBeta) * 90.f; size_t uiNumber = glm::clamp(static_cast<unsigned int>(m_level), 1u, 5u); for(size_t i = 0; i < uiNumber; i++) { CPoisonProjectile * projectile = new CPoisonProjectile(); m_projectiles.push_back(projectile); } m_duration = GameDurationMs(8000); m_hasDuration = true; GameDuration lMax = 0; for(size_t i = 0; i < m_projectiles.size(); i++) { CPoisonProjectile * projectile = m_projectiles[i]; projectile->Create(srcPos, afBeta + Random::getf(-10.f, 10.f)); GameDuration lTime = m_duration + GameDurationMs(Random::getu(0, 5000)); projectile->SetDuration(lTime); lMax = std::max(lMax, lTime); EERIE_LIGHT * light = dynLightCreate(projectile->lLightId); if(light) { light->intensity = 2.3f; light->fallend = 250.f; light->fallstart = 150.f; light->rgb = Color3f::green; light->pos = projectile->eSrc; light->creationTime = g_gameTime.now(); light->duration = GameDurationMs(200); } } m_duration = lMax + GameDurationMs(1000); }