C4Value C4Effect::DoCall(C4Object *pObj, const char *szFn, C4Value &rVal1, C4Value &rVal2, C4Value &rVal3, C4Value &rVal4, C4Value &rVal5, C4Value &rVal6, C4Value &rVal7) { // def script or global only? C4AulScript *pSrcScript; C4Def *pDef; if (pCommandTarget) { pSrcScript = &pCommandTarget->Def->Script; // overwrite ID for sync safety in runtime join idCommandTarget = pCommandTarget->id; } else if (idCommandTarget && (pDef = Game.Defs.ID2Def(idCommandTarget))) pSrcScript = &pDef->Script; else pSrcScript = &Game.ScriptEngine; // compose function name char fn[C4AUL_MAX_Identifier + 1]; sprintf(fn, PSF_FxCustom, Name, szFn); // call it C4AulFunc *pFn = pSrcScript->GetFuncRecursive(fn); if (!pFn) return C4Value(); return pFn->Exec(pCommandTarget, &C4AulParSet(C4VObj(pObj), C4VInt(iNumber), rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); }
C4Value C4PropList::Call(C4String * k, C4AulParSet *Pars, bool fPassErrors) { if (!Status) return C4Value(); C4AulFunc *pFn = GetFunc(k); if (!pFn) return C4Value(); return pFn->Exec(this, Pars, fPassErrors); }
C4AulFunc * C4AulFuncMap::GetNextSNFunc(const C4AulFunc * After) { C4AulFunc * Func = After->MapNext; while (Func && After->GetName() != Func->GetName()) Func = Func->MapNext; return Func; }
std::list<const char*> C4AulScriptEngine::GetFunctionNames(C4PropList * p) { std::list<const char*> functions; std::list<const char*> global_functions; auto sort_alpha = [](const char * const &a, const char * const &b) -> bool { return strcmp(a, b) < 0; }; if (!p) p = GetPropList(); const C4ValueArray * a = p->GetProperties(); for (int i = 0; i < a->GetSize(); ++i) { C4String * key = (*a)[i].getStr(); if (!key) continue; C4AulFunc * f = p->GetFunc(key); if (!f) continue; if (!f->GetPublic()) continue; if (!::ScriptEngine.GetPropList()->HasProperty(key)) functions.push_back(key->GetCStr()); else global_functions.push_back(key->GetCStr()); } delete a; functions.sort(sort_alpha); if (!functions.empty() && !global_functions.empty()) functions.push_back(0); // separator global_functions.sort(sort_alpha); functions.splice(functions.end(), global_functions); return functions; }
C4Value C4PropList::Call(const char * s, C4AulParSet *Pars, bool fPassErrors) { if (!Status) return C4Value(); assert(s && s[0]); C4AulFunc *pFn = GetFunc(s); if (!pFn) return C4Value(); return pFn->Exec(this, Pars, fPassErrors); }
C4AulFunc * C4AulFuncMap::GetFirstFunc(C4String * Name) { if (!Name) return NULL; C4AulFunc * Func = Funcs[Hash(Name->GetCStr()) % HashSize]; while (Func && Name->GetCStr() != Func->GetName()) Func = Func->MapNext; return Func; }
C4AulFunc * C4AulFuncMap::GetFirstFunc(const char * Name) { if (!Name) return nullptr; C4AulFunc * Func = Funcs[Hash(Name) % HashSize]; while (Func && !SEqual(Name, Func->GetName())) Func = Func->MapNext; return Func; }
void C4PropertyDlg::UpdateInputCtrl(C4Object *pObj) { int cnt; #ifdef WITH_DEVELOPER_MODE GtkEntryCompletion *completion = gtk_entry_get_completion(GTK_ENTRY(entry)); GtkListStore *store; // Uncouple list store from completion so that the completion is not // notified for every row we are going to insert. This enhances // performance significantly. if (!completion) { completion = gtk_entry_completion_new(); store = gtk_list_store_new(1, G_TYPE_STRING); gtk_entry_completion_set_text_column(completion, 0); gtk_entry_set_completion(GTK_ENTRY(entry), completion); g_object_unref(G_OBJECT(completion)); } else { store = GTK_LIST_STORE(gtk_entry_completion_get_model(completion)); g_object_ref(G_OBJECT(store)); gtk_entry_completion_set_model(completion, NULL); } GtkTreeIter iter; gtk_list_store_clear(store); #endif // WITH_DEVELOPER_MODE // add global and standard functions for (C4AulFunc *pFn = Game.ScriptEngine.GetFirstFunc(); pFn; pFn = Game.ScriptEngine.GetNextFunc(pFn)) if (pFn->GetPublic()) { SCopy(pFn->Name, OSTR); #ifdef WITH_DEVELOPER_MODE gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, OSTR, -1); #endif } // Add object script functions C4AulScriptFunc *pRef; // Object script available if (pObj && pObj->Def) // Scan all functions for (cnt = 0; pRef = pObj->Def->Script.GetSFunc(cnt); cnt++) // Public functions only if (pRef->Access = AA_PUBLIC) { // Add function SCopy(pRef->Name, OSTR); #ifdef WITH_DEVELOPER_MODE gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, OSTR, -1); #endif } #if WITH_DEVELOPER_MODE // Reassociate list store with completion gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); #endif }
int32_t C4SortObjectFunc::CompareGetValue(C4Object *pObj) { // Function not found? if (!pFunc) return false; // Search same-name-list for appropriate function C4AulFunc *pCallFunc = pFunc->FindSameNameFunc(pObj->Def); if (!pCallFunc) return false; // Call return pCallFunc->Exec(pObj, &Pars).getInt(); }
bool C4FindObjectFunc::Check(C4Object *pObj) { // Function not found? if (!pFunc) return false; // Search same-name-list for appropriate function C4AulFunc *pCallFunc = pFunc->FindSameNameFunc(pObj->Def); if (!pCallFunc) return false; // Call return !!pCallFunc->Exec(pObj, &Pars); }
void C4Effect::CallDamage(int32_t & damage, int damagetype, int plr) { if (!GetCallbackScript()) { C4AulFunc *pFn = GetFunc(P_Damage); if (pFn) damage = pFn->Exec(this, &C4AulParSet(damage, damagetype, plr)).getInt(); } else if (pFnDamage) damage = pFnDamage->Exec(GetCallbackScript(), &C4AulParSet(Obj(Target), this, damage, damagetype, plr)).getInt(); }
C4Value C4Effect::DoCall(C4PropList *pObj, const char *szFn, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4, const C4Value &rVal5, const C4Value &rVal6, const C4Value &rVal7) { C4PropList * p = GetCallbackScript(); if (!p) { C4AulFunc * fn = GetFunc(szFn); if (fn) return fn->Exec(this, &C4AulParSet(rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); } else { // old variant // compose function name C4AulFunc * fn = p->GetFunc(FormatString(PSF_FxCustom, GetName(), szFn).getData()); if (fn) return fn->Exec(p, &C4AulParSet(Obj(pObj), this, rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7)); } return C4Value(); }
void C4AulScript::AppendTo(C4AulScript &Scr, bool bHighPrio) { // definition appends if (Def && Scr.Def) Scr.Def->IncludeDefinition(Def); // append all funcs // (in reverse order if inserted at begin of list) C4AulScriptFunc *sf; for (C4AulFunc *f = bHighPrio ? Func0 : FuncL; f; f = bHighPrio ? f->Next : f->Prev) // script funcs only if (sf = f->SFunc()) // no need to append global funcs if (sf->Access != AA_GLOBAL) { // append: create copy // (if high priority, insert at end, otherwise at the beginning) C4AulScriptFunc *sfc = new C4AulScriptFunc(&Scr, sf->Name, bHighPrio); sfc->CopyBody(*sf); // link the copy to a local function if (sf->LinkedTo) { sfc->LinkedTo = sf->LinkedTo; sf->LinkedTo = sfc; } else { sfc->LinkedTo = sf; sf->LinkedTo = sfc; } } // mark as linked // increase code size needed Scr.CodeSize += CodeSize + 1; // append all local vars (if any existing) assert(!Def || this == &Def->Script); assert(&Scr.Def->Script == &Scr); if (LocalNamed.iSize == 0) return; if (!Scr.Def) { Warn("could not append local variables to global script!", ""); return; } // copy local var definitions for (int ivar = 0; ivar < LocalNamed.iSize; ivar++) Scr.LocalNamed.AddName(LocalNamed.pNames[ivar]); }
void C4AulScript::UnLink() { // unlink children for (C4AulScript *s = Child0; s; s = s->Next) s->UnLink(); // do not unlink temporary (e.g., DirectExec-script in ReloadDef) if (Temporary) return; // check if byte code needs to be freed if (Code) { delete[] Code; Code = NULL; } // delete included/appended functions C4AulFunc *pFunc = Func0; while (pFunc) { C4AulFunc *pNextFunc = pFunc->Next; // clear stuff that's set in AfterLink pFunc->UnLink(); if (pFunc->SFunc()) if (pFunc->Owner != pFunc->SFunc()->pOrgScript) if (!pFunc->LinkedTo || pFunc->LinkedTo->SFunc()) // do not kill global links; those will // be deleted if corresponding sfunc in // script is deleted delete pFunc; pFunc = pNextFunc; } // includes will have to be re-resolved now IncludesResolved = false; if (State > ASS_PREPARSED) State = ASS_PREPARSED; }