diff --git a/dar2oar_core/src/condition_parser/conditions.rs b/dar2oar_core/src/condition_parser/conditions.rs index c8fc1a4..77602a0 100644 --- a/dar2oar_core/src/condition_parser/conditions.rs +++ b/dar2oar_core/src/condition_parser/conditions.rs @@ -11,7 +11,7 @@ use crate::conditions::{ IsWornHasKeyword, Level, Or, RandomCondition, }; use crate::dar_syntax::syntax::{self, Expression}; -use crate::values::{Cmp, DirectionValue, NumericValue}; +use crate::values::{Cmp, DirectionValue}; pub fn parse_conditions(input: syntax::Condition) -> Result { Ok(match input { @@ -47,16 +47,10 @@ fn parse_condition(condition: Expression<'_>) -> Result parse_compare(fn_name, args, negated)?, - actor if fn_name.starts_with("IsActor") => parse_actor(actor, args, negated)?, - "IsInFaction" | "IsFactionRankEqualTo" | "IsFactionRankLessThan" => { - parse_faction(fn_name, args, negated)? - } - equip if fn_name.starts_with("IsEquipped") => parse_equip(equip, args, negated)?, - "IsLevelLessThan" => ConditionSet::Level(Level { + "CurrentGameTimeLessThan" => ConditionSet::CurrentGameTime(CurrentGameTime { negated, comparison: Cmp::Lt, - numeric_value: args.try_get(0, "NumericValue")?.into(), + numeric_value: args.try_get(0, "NumericValue for CurrentGameTime")?.into(), ..Default::default() }), "CurrentWeather" => gen_cond!( @@ -64,7 +58,6 @@ fn parse_condition(condition: Expression<'_>) -> Result gen_cond!(IsRace(race, negated), args, "PluginValue for IsRace"), "IsClass" => gen_cond!(IsClass(class, negated), args, "PluginValue for IsClass"), "IsCombatStyle" => { gen_cond!( @@ -73,23 +66,23 @@ fn parse_condition(condition: Expression<'_>) -> Result { - gen_cond!( - IsVoiceType(voice_type, negated), - args, - "PluginValue for IsVoiceType" - ) + actor if fn_name.starts_with("IsActor") => parse_actor(actor, args, negated)?, + equip if fn_name.starts_with("IsEquipped") => parse_equip(equip, args, negated)?, + "IsInFaction" | "IsFactionRankEqualTo" | "IsFactionRankLessThan" => { + parse_faction(fn_name, args, negated)? } + "IsInLocation" => gen_cond!(IsInLocation(location, negated), args, "IsInLocation"), + "IsLevelLessThan" => ConditionSet::Level(Level { + negated, + comparison: Cmp::Lt, + numeric_value: args.try_get(0, "NumericValue for Level")?.into(), + ..Default::default() + }), "IsParentCell" => gen_cond!( IsParentCell(cell, negated), args, "PluginValue for IsParentCell" ), - "IsWorldSpace" => gen_cond!( - IsWorldSpace(world_space, negated), - args, - "PluginValue for IsWorldSpace" - ), "IsMovementDirection" => ConditionSet::IsDirectionMovement(IsMovementDirection { negated, direction: DirectionValue { @@ -97,7 +90,19 @@ fn parse_condition(condition: Expression<'_>) -> Result gen_cond!(IsInLocation(location, negated), args, "IsInLocation"), + "IsRace" => gen_cond!(IsRace(race, negated), args, "PluginValue for IsRace"), + "IsVoiceType" => { + gen_cond!( + IsVoiceType(voice_type, negated), + args, + "PluginValue for IsVoiceType" + ) + } + "IsWorldSpace" => gen_cond!( + IsWorldSpace(world_space, negated), + args, + "PluginValue for IsWorldSpace" + ), "IsWorn" => gen_cond!(IsWorn(form, negated), args, "IsWorn"), "IsWornHasKeyword" => gen_cond!( IsWornHasKeyword(keyword, negated), @@ -112,19 +117,22 @@ fn parse_condition(condition: Expression<'_>) -> Result ConditionSet::CurrentGameTime(CurrentGameTime { + "ValueEqualTo" | "ValueLessThan" => parse_compare(fn_name, args, negated)?, + + // Conditional expressions without any arguments + // This enumeration order is the same as the DAR docs. + "IsFemale" | "IsChild" | "IsPlayerTeammate" | "IsInInterior" | "IsUnique" + | "IsAttacking" | "IsRunning" | "IsSneaking" | "IsSprinting" | "IsInAir" | "IsInCombat" + | "IsWeaponDrawn" => ConditionSet::Condition(Condition { + condition: fn_name.into(), negated, - comparison: Cmp::Lt, - numeric_value: NumericValue::StaticValue(args[0].clone().try_into().unwrap()), ..Default::default() }), - _ => { - tracing::debug!("Condition({fn_name}) has no explicit mapping."); - ConditionSet::Condition(Condition { - condition: fn_name.into(), - negated, - ..Default::default() - }) + unknown_condition => { + return Err(ParseError::UnexpectedValue( + "Unknown condition: ".into(), + unknown_condition.into(), + )) } }) } diff --git a/dar2oar_core/src/condition_parser/equip.rs b/dar2oar_core/src/condition_parser/equip.rs index 003f7ce..091b858 100644 --- a/dar2oar_core/src/condition_parser/equip.rs +++ b/dar2oar_core/src/condition_parser/equip.rs @@ -1,7 +1,7 @@ -use super::macros::get_try_into; +use super::macros::{gen_cond, get_try_into}; use super::{dar_interface::ParseError, macros::GetArg as _}; use crate::{ - conditions::{ConditionSet, IsEquipped, IsEquippedHasKeyword, IsEquippedType}, + conditions::{ConditionSet, IsEquipped, IsEquippedHasKeyword, IsEquippedShout, IsEquippedType}, dar_syntax::syntax::FnArg, values::{NumericLiteral, TypeValue}, }; @@ -40,6 +40,16 @@ pub(super) fn parse_equip( ..Default::default() }) } - _ => unreachable!(), + "IsEquippedShout" => gen_cond!( + IsEquippedShout(shout, negated), + args, + "shout(PluginValue) in IsEquippedShout" + ), + _ => { + return Err(ParseError::UnexpectedValue( + "IsEquipped prefix condition unexpected to come in: ".to_string(), + condition_name.to_string(), + )) + } }) } diff --git a/dar2oar_core/src/condition_parser/macros.rs b/dar2oar_core/src/condition_parser/macros.rs index 1edc5c4..8ef5ce7 100644 --- a/dar2oar_core/src/condition_parser/macros.rs +++ b/dar2oar_core/src/condition_parser/macros.rs @@ -83,7 +83,7 @@ macro_rules! gen_cond { ConditionSet::$id($id { negated: $negated, $field_name: - > as $crate::condition_parser::macros::GetArg>::try_get(&$args,0, $expected)?.into(), + > as $crate::condition_parser::macros::GetArg>::try_get(&$args, 0, $expected)?.into(), ..Default::default() }) }; diff --git a/dar2oar_core/src/values/type_value.rs b/dar2oar_core/src/values/type_value.rs index f25a0e5..eccefd1 100644 --- a/dar2oar_core/src/values/type_value.rs +++ b/dar2oar_core/src/values/type_value.rs @@ -90,11 +90,11 @@ impl TryFrom for WeaponType { fn try_from(value: NumericLiteral) -> Result { match value { NumericLiteral::Hex(num) => match num { - 1..=18 => Ok((num as i64).try_into().expect("unreachable")), + 1..=18 => Ok((num as i64).try_into()?), _ => Err("Got hex, Out of range 1..=18"), }, NumericLiteral::Decimal(num) => match num { - -1..=18 => Ok((num as i64).try_into().expect("unreachable")), + -1..=18 => Ok((num as i64).try_into()?), _ => Err("Got Decimal, Out of range -1..=18"), }, NumericLiteral::Float(num) => Ok(num.to_string().as_str().try_into()?),