194 lines
5.8 KiB
C#
194 lines
5.8 KiB
C#
using System;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
|
|
using CLRScriptFramework;
|
|
using NWScript;
|
|
using NWScript.ManagedInterfaceLayer.NWScriptManagedInterface;
|
|
|
|
using NWEffect = NWScript.NWScriptEngineStructure0;
|
|
using NWEvent = NWScript.NWScriptEngineStructure1;
|
|
using NWLocation = NWScript.NWScriptEngineStructure2;
|
|
using NWTalent = NWScript.NWScriptEngineStructure3;
|
|
using NWItemProperty = NWScript.NWScriptEngineStructure4;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
namespace CLRScript
|
|
{
|
|
class Agent : CLRScriptBase{
|
|
public uint objref;
|
|
|
|
public Agent(uint obj){
|
|
objref = obj;
|
|
}
|
|
|
|
public float facing{
|
|
get{
|
|
return _facing;
|
|
}
|
|
set{
|
|
_facing = value;
|
|
AssignCommand(objref, ()=>{SetFacing(_facing, TRUE);});
|
|
}
|
|
}
|
|
|
|
public NWLocation loc{
|
|
get{
|
|
return _loc;
|
|
}
|
|
set{
|
|
_loc = value;
|
|
AssignCommand(objref, ()=>{ActionForceMoveToLocation(_loc, TRUE, 6f);});
|
|
|
|
//Link effect
|
|
RemoveSEFFromObject(objref, "nwai_beam_loc");
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectNWN2SpecialEffectFile("nwai_beam_loc", OBJECT_INVALID, GetPositionFromLocation(_loc)), objref, -1f);
|
|
}
|
|
}
|
|
|
|
//Detection
|
|
//=======================================================================
|
|
|
|
public bool hasWallFront(float distance=10f){
|
|
Vector3 pointFront = Add(GetPositionFromLocation(loc), Multiply(AngleToVector(facing), distance));
|
|
return LineOfSightVector(GetPosition(objref), pointFront)==1;
|
|
}
|
|
|
|
public bool isInCombat(){
|
|
return GetIsInCombat(objref)==1;
|
|
}
|
|
|
|
//Json containing
|
|
// {"valid":"true", "id":"366642", "name":"Goblin", "distance":"13.37", "difficulty":"13", "hp":"12"}
|
|
public dynamic getNearestEnemy(float distanceMax=15f){
|
|
uint nearestEnemy = GetNearestCreature(
|
|
CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY,
|
|
objref, 1,
|
|
CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN_AND_HEARD,
|
|
CREATURE_TYPE_IS_ALIVE, CREATURE_ALIVE_TRUE);
|
|
|
|
|
|
float dist = GetDistanceBetween(nearestEnemy, objref);
|
|
return JsonConvert.DeserializeObject<dynamic>("{"
|
|
+ "\"valid\":\""+(GetIsObjectValid(nearestEnemy)==TRUE && dist<=distanceMax).ToString()+"\","
|
|
+ "\"id\":\""+(nearestEnemy).ToString()+"\","
|
|
+ "\"name\":\""+GetName(nearestEnemy)+"\""
|
|
+ "\"distance\":\""+(dist).ToString()+"\","
|
|
+ "\"difficulty\":\""+GetChallengeRating(nearestEnemy)+"\""
|
|
+ "\"hp\":\""+GetCurrentHitPoints(nearestEnemy)+"\""
|
|
+ "}");
|
|
}
|
|
|
|
//Json containing
|
|
// {"valid":"true", "id":"366642", "name":"Guethenoc", "distance":"13.37"}
|
|
public dynamic getNearestPlayer(float distanceMax=15f){
|
|
uint pc = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, objref, 1, -1,-1,-1,-1);
|
|
|
|
float dist = GetDistanceBetween(pc, objref);
|
|
return JsonConvert.DeserializeObject<dynamic>("{"
|
|
+ "\"valid\":\""+(GetIsObjectValid(pc)==TRUE && dist<=distanceMax).ToString()+"\","
|
|
+ "\"id\":\""+(pc).ToString()+"\","
|
|
+ "\"name\":\""+GetName(pc)+"\""
|
|
+ "\"distance\":\""+(dist).ToString()+"\","
|
|
+ "}");
|
|
}
|
|
|
|
//Actions
|
|
//=======================================================================
|
|
|
|
public bool moveForward(float distance=10f){
|
|
if(hasWallFront(distance))
|
|
return false;
|
|
|
|
//See NWN2DataLib.AreaSurfaceMesh.PathExists
|
|
|
|
Vector3 pointFront = Add(GetPositionFromLocation(loc), Multiply(AngleToVector(facing), distance));
|
|
loc = Location(GetAreaFromLocation(loc), pointFront, facing);
|
|
return true;
|
|
}
|
|
|
|
public bool attackNearest(float distanceMax=15f){
|
|
var nearest = getNearestEnemy(distanceMax);
|
|
if(!nearest.valid)
|
|
return false;
|
|
|
|
AssignCommand(objref, ()=>{ActionAttack(nearest.id, FALSE);});
|
|
return true;
|
|
}
|
|
|
|
public bool turn(float angleDeg){
|
|
facing+=angleDeg;
|
|
return true;
|
|
}
|
|
|
|
public bool say(string message){
|
|
AssignCommand(objref, ()=>{SpeakString(message, TALKVOLUME_TALK);});
|
|
|
|
return getNearestPlayer().valid;
|
|
}
|
|
|
|
public string callCommand(string command)
|
|
{
|
|
Regex regexMethod = new Regex(@"([a-zA-Z_]+?)\s*\((.*?)\)");
|
|
Regex regexParam = new Regex("(\".*?\"|[0-9\\.]+)");
|
|
|
|
string methodName;
|
|
List<string> unparsedParams = new List<string>();
|
|
|
|
MatchCollection matches = regexMethod.Matches(command);
|
|
if(matches.Count == 1){
|
|
//Match name
|
|
methodName = matches[0].Groups[1].ToString();
|
|
|
|
//March parameters
|
|
string methodParamList = matches[0].Groups[2].ToString();
|
|
MatchCollection paramMatches = regexParam.Matches(methodParamList);
|
|
foreach(var p in paramMatches){
|
|
unparsedParams.Add(p.ToString().Trim('"'));
|
|
}
|
|
}
|
|
else{
|
|
//Failed to parse command
|
|
return "";
|
|
}
|
|
|
|
MethodInfo method = this.GetType().GetMethod(methodName);
|
|
ParameterInfo[] methodParams = method.GetParameters();
|
|
|
|
if(methodParams.Length != unparsedParams.Count){
|
|
//Incorrect number of parameters
|
|
return "";
|
|
}
|
|
|
|
|
|
List<Object> parsedParams = new List<Object>();
|
|
for(int i=0 ; i<methodParams.Length ; i++){
|
|
//Handle defaults?
|
|
var typeConverter = TypeDescriptor.GetConverter(methodParams[i].ParameterType);
|
|
parsedParams.Add(typeConverter.ConvertFromString(unparsedParams[i]));
|
|
}
|
|
|
|
|
|
return method.Invoke(this, parsedParams.ToArray()).ToString();
|
|
}
|
|
|
|
|
|
|
|
|
|
private float _facing;
|
|
private NWLocation _loc;
|
|
|
|
private Vector3 Multiply(Vector3 v, float f) {
|
|
v.x*=f; v.y*=f; v.z*=f;
|
|
return v;
|
|
}
|
|
private Vector3 Add(Vector3 v, Vector3 w) {
|
|
v.x*=w.x; v.y*=w.y; v.z*=w.z;
|
|
return v;
|
|
}
|
|
}
|
|
}
|