void ActorArmourProto::link() { if(m_is_actor) actor = index(); else actor.link(); ASSERT(actor); armour.link(); for(int st = 0; st < Stance::count; st++) for(int su = 0; su < SurfaceId::count; su++) { char name[256]; snprintf(name, sizeof(name), "%s%s%s%s", st == Stance::prone? "prone" : "stand", actor->is_heavy? "heavy" : "normal", armour->sound_prefix.c_str(), SurfaceId::toString(su)); step_sounds[st][su] = SoundId(name); } { ArmourClass::Type class_id = armour? armour->class_id : ArmourClass::none; const char *postfix = class_id == ArmourClass::leather? "leath" : class_id == ArmourClass::metal? "metal" : class_id == ArmourClass::power || class_id == ArmourClass::environmental? "pow" : "cloth"; char fall_sound_name[256]; snprintf(fall_sound_name, sizeof(fall_sound_name), "bfall_%s_%s", actor->is_heavy? "heavy" : "normal", postfix); fall_sound = fall_sound_name; } }
void ActorProto::link() { ActorArmourProto::link(); punch_weapon.link(); kick_weapon.link(); char text[256]; for(int d = 0; d < DeathId::count; d++) { snprintf(text, sizeof(text), "human%s", deathName(d)); human_death_sounds[d] = SoundId(text); } snprintf(text, sizeof(text), "%srun", sound_prefix.c_str()); run_sound = text; snprintf(text, sizeof(text), "%swalk", sound_prefix.c_str()); walk_sound = text; for(int n = 0;; n++) { char var_name[128]; snprintf(var_name, sizeof(var_name), n == 0? "%s" : "%s%d", sound_prefix.c_str(), n); Sounds sounds; bool any_sound = false; for(int d = 0; d < DeathId::count; d++) { snprintf(text, sizeof(text), "%s%s", var_name, deathName(d)); sounds.death[d] = SoundId(text); any_sound |= sounds.death[d].isValid(); } snprintf(text, sizeof(text), "%sgetup", var_name); sounds.get_up = text; snprintf(text, sizeof(text), "%shit", var_name); sounds.hit = text; any_sound |= sounds.get_up.isValid() | sounds.hit.isValid(); if(!any_sound && n >= 1) break; if(any_sound) this->sounds.emplace_back(sounds); } if(sounds.empty()) sounds.emplace_back(Sounds()); }
TurretProto::TurretProto(const TupleParser &parser) :ProtoImpl(parser) { ASSERT(!is_dummy); ASSERT(sprite); hit_points = toFloat(parser("hit_points")); for(int n = 0; n < TurretAction::count; n++) anim_idx[n] = sprite->findSequence(s_seq_names[n]); ASSERT(anim_idx[TurretAction::idle] != -1); string sound_prefix = parser("sound_prefix"); for(int n = 0; n < TurretSoundId::count; n++) { string sound_name = sound_prefix + s_sounds[n].name; sound_idx[n] = SoundId(sound_name.c_str(), s_sounds[n].index); } }
DoorProto::DoorProto(const TupleParser &parser) :ProtoImpl(parser) { ASSERT(!is_dummy); name = parser("name"); class_id = fromString<DoorClassId>(parser("class_id")); const char *sound_prefix = parser("sound_prefix"); for(auto dstype : all<DoorSoundType>()) { char name[256]; snprintf(name, sizeof(name), "%s%s", sound_prefix, toString(dstype)); sound_ids[dstype] = SoundId(name); } for(auto ds : all<DoorState>()) seq_ids[ds] = sprite->findSequence(s_seq_names[ds]); if(seq_ids[DoorState::closed] == -1) THROW("Missing sequence: %s", s_seq_names[DoorState::closed]); bool can_open_in = seq_ids[DoorState::opened_in] != -1 && seq_ids[DoorState::opening_in] != -1 && seq_ids[DoorState::closing_in] != -1; bool can_open_out = seq_ids[DoorState::opened_out] != -1 && seq_ids[DoorState::opening_out] != -1 && seq_ids[DoorState::closing_out] != -1; bool error = false; if((class_id == DoorClassId::sliding || class_id == DoorClassId::rotating || class_id == DoorClassId::rotating_in) && !can_open_in) error = true; if((class_id == DoorClassId::rotating || class_id == DoorClassId::rotating_out) && !can_open_out) error = true; if(class_id == DoorClassId::sliding && can_open_out) error = true; if(error) THROW("Invalid sequence combination"); }
WeaponProto::WeaponProto(const TupleParser &parser) :ProtoImpl(parser) { ammo_class_id = parser("ammo_class_id"); impact = parser("impact_id"); projectile = parser("projectile_id"); class_id = fromString<WeaponClass>(parser("class_id")); damage_mod = parser.get<float>("damage_mod"); attack_modes = AttackModeFlags::fromString(parser("attack_modes")); max_ammo = parser.get<int>("max_ammo"); burst_ammo = parser.get<int>("burst_ammo"); ranged_range = melee_range = 0.0f; accuracy = parser.get<float>("accuracy"); const char *sound_prefix = parser("sound_prefix"); for(auto wstype : all<WeaponSoundType>()) { char name[256]; snprintf(name, sizeof(name), "%s%s", sound_prefix, s_suffixes[wstype]); sound_ids[wstype] = SoundId(name); } if(!sound_ids[WeaponSoundType::normal].isValid()) sound_ids[WeaponSoundType::normal] = sound_ids[WeaponSoundType::fire_single]; }
WeaponProto::WeaponProto(const TupleParser &parser) :ProtoImpl(parser) { ammo_class_id = parser("ammo_class_id"); impact = parser("impact_id"); projectile = parser("projectile_id"); class_id = WeaponClass::fromString(parser("class_id")); damage_mod = toFloat(parser("damage_mod")); attack_modes = AttackModeFlags::fromString(parser("attack_modes")); max_ammo = toInt(parser("max_ammo")); burst_ammo = toInt(parser("burst_ammo")); ranged_range = melee_range = 0.0f; accuracy = toFloat(parser("accuracy")); const char *sound_prefix = parser("sound_prefix"); for(int n = 0; n < WeaponSoundType::count; n++) { char name[256]; snprintf(name, sizeof(name), "%s%s", sound_prefix, WeaponSoundType::toString(n)); sound_ids[n] = SoundId(name); } if(!sound_ids[WeaponSoundType::normal].isValid()) sound_ids[WeaponSoundType::normal] = sound_ids[WeaponSoundType::fire_single]; }