/// This global gets set to the verb in question each time the stack manager calls verb_call entity verb; //.entity current_verb; //.float verb_done; /// Execure this verb #define VCM_DO 0 /// Return the value of this verb. Return VS_CALL_REMOVE to delete it. #define VCM_EVAL 1 /// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE) #define VCM_REMOVE 2 /// Verb callback .float(float message) verb_call; /// Points to this verb's stack. .entity verbstack; /// Static value of this verb .float verb_static_value; /// verb_call returns this when a verb in not doable #define VS_CALL_NO 0 /// verb_call(VCM_DO) returns this when a verb is executing #define VS_CALL_YES_DOING -1 /// verb_call(VCM_DO) returns this when a verb did execure and is done #define VS_CALL_YES_DONE -2 /// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager #define VS_CALL_REMOVE -3 /* void verbstack_updatechain(entity stack) { entity vrb, v; if not (stack) return; dprint("verbstack_updatechain\n"); vrb = findchainentity(verbstack, stack); if not (vrb) { stack.vchain = world; return; } stack.vchain = vrb; v = vrb; while(vrb) { vrb = vrb.chain; } } void verbstack_remove(entity vverb) { entity vstack; dprint("verbstack_remove\n"); vstack = verb.verbstack; remove(vverb); vverb.verbstack = world; verbstack_updatechain(vstack); //vverb.think = SUB_Remove; //vverb.nextthink = time; } void verbstack_thinkremove() { dprint("verbstack_thinkremove\n"); verbstack_remove(self); } */ /** Push a new verb onto the specified stack. Set vrb_life to make it time-limited. **/ entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner) { entity vrb; if not(stack) return world; if not(vrb_call) return world; vrb = spawn(); vrb.owner = verb_owner; vrb.verbstack = stack; vrb.verb_call = vrb_call; vrb.verb_static_value = val_static; vrb.classname = "verb"; stack.classname = "verbstack"; if(vrb_life) { //vrb.think = verbstack_thinkremove; vrb.think = SUB_Remove; vrb.nextthink = time + vrb_life; } //verbstack_updatechain(stack); return vrb; } /** Find the best verb in this stack and execurte it. ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO **/ float verbstack_pop(entity stack) { entity vrb, bestverb, oldself; float value, bestvalue; oldself = self; vrb = findchainentity(verbstack,stack); //vrb = stack.vchain; //dprint("owner:", stack.owner.classname, " vsn:", stack.classname,"\n"); while(vrb) { //dprint("vn:", vrb.classname,"\n"); verb = vrb; vrb = vrb.chain; self = verb.owner; value = verb.verb_call(VCM_EVAL); if(value < 0) { if(value == VS_CALL_REMOVE) remove(verb); } else { if(value > bestvalue) { bestverb = verb; bestvalue = value; } } } if(bestverb) { verb = bestverb; self = verb.owner; value = verb.verb_call(VCM_DO); if(value == VS_CALL_REMOVE) remove(bestverb); } self = oldself; return value; } float verbstack_popfifo(entity stack) { entity oldself; float ret; oldself = self; verb = findentity(stack,verbstack,stack); if not (verb) ret = 0; else { self = verb.owner; ret = verb.verb_call(VCM_DO); if(ret == VS_CALL_REMOVE) remove(verb); } self = oldself; return ret; } /** Find the best verb in this stack and return it. ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL. **/ entity verbstack_pull(entity stack) { entity vrb; entity bestverb, oldself; float value, bestvalue; oldself = self; vrb = findchainentity(verbstack,stack); while(vrb) { self = vrb.owner; verb = vrb; vrb = vrb.chain; value = verb.verb_call(VCM_EVAL); if(value < 0) { if(value == VS_CALL_REMOVE) remove(verb); } else { if(value > bestvalue) { bestverb = verb; bestvalue = value; } } } self = oldself; return bestverb; } entity verbstack_pullfifo(entity stack) { return findentity(stack,verbstack,stack); } /** Delete every verb on this stack, signaling them with VCM_REMOVE first. **/ void verbstack_flush(entity stack) { entity vrb, oldself; oldself = self; vrb = findchainentity(verbstack,stack); while(vrb) { self = vrb.owner; verb = vrb; vrb = vrb.chain; verb.verb_call(VCM_REMOVE); remove(verb); } self = oldself; //stack.vchain = world; } void verbstack_doverb(entity vrb) { float value; verb = vrb; self = verb.owner; value = verb.verb_call(VCM_DO); if(value == VS_CALL_REMOVE) remove(vrb); }