/// <summary> /// Handles the given event. /// </summary> /// <param name="aiEvent"></param> private void HandleEvent(IAiEvent aiEvent) { if (aiEvent is HitEvent hitEvent) { var handle = hitEvent.AttackerHandle; if (!_hateLevels.TryGetValue(handle, out var hate)) { hate = 0; } _hateLevels[handle] = hate + _hateGetHit; var attacker = this.Entity.Map.GetCharacter(handle); if (attacker != null) { this.Entity.Direction = this.Entity.Position.GetDirection(attacker.Position); Send.ZC_ROTATE(this.Entity); } var callback = _eventCallbacks.FirstOrDefault(a => a.StateName == this.CurrentStateName && a.EventName == aiEvent.EventName); if (callback != null && this.ExecuteEvent(callback.CallbackName, aiEvent) != LuaFuncResult.Yielded) { lua_settop(GL, 0); return; } } }
/// <summary> /// Executes the function with the given name and returns whether /// it yielded. /// </summary> /// <param name="callbackName"></param> /// <param name="aiEvent"></param> /// <returns></returns> private LuaFuncResult ExecuteEvent(string callbackName, IAiEvent aiEvent) { // Clear stack and any states that were potentially running. _currentRoutine = null; lua_settop(GL, 0); NL = lua_newthread(GL); lua_getglobal(NL, callbackName); if (!lua_isfunction(NL, -1)) { Log.Error("EntityAi: Function '{0}' not defined.", callbackName); lua_settop(NL, 0); return(LuaFuncResult.Fail); } var argc = aiEvent.PushArguments(NL); var stateResult = lua_resume(NL, argc); if (stateResult != 0 && stateResult != LUA_YIELD) { Log.Error("EntityAi: Error while exuting state function: {0}", lua_tostring(NL, -1)); lua_settop(NL, 0); return(LuaFuncResult.Fail); } // If the function completed, nothing yielded, so pop // the newly created thread and let the AI get back to // its current state on the next tick. if (stateResult == 0) { lua_settop(GL, 0); return(LuaFuncResult.Success); } return(LuaFuncResult.Yielded); }
/// <summary> /// Queues up event for the AI to react to on the next tick. /// </summary> /// <param name="aiEvent"></param> public void QueueEvent(IAiEvent aiEvent) { lock (_events) _events.Enqueue(aiEvent); }