LTBOOL CAISenseSeeAllyDeath::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta) { if ( !IsBody(hStimulus) ) return LTFALSE; if ( m_pAI->IsObjectVisibleFromEye(CAI::BodyFilterFn, NULL, hStimulus, (m_fDistanceSqr), LTTRUE) ) { React(); return LTTRUE; } return LTFALSE; }
LTBOOL CAISenseHearAllyDeath::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta) { if ( !IsBody(hStimulus) ) return LTFALSE; CDeathScene* pDeathScene = g_pCharacterMgr->GetDeathScene(hStimulus); if ( !pDeathScene ) return LTFALSE; // Time has got to be greater than the death scene noise time but not too much greater if ( g_pLTServer->GetTime() > pDeathScene->GetNoiseTime() && g_pLTServer->GetTime() < pDeathScene->GetNoiseTime() + 1.0f ) { // Noise has to be within audible radius LTFLOAT fDistance = VEC_DIST(pDeathScene->GetPosition(), m_pAI->GetPosition()); LTFLOAT fDeathSceneNoiseDistance = g_pAIButeMgr->GetSenses()->fAllyDeathNoiseDistance; fDeathSceneNoiseDistance *= pDeathScene->GetNoiseVolume(); if ( fDistance < (m_fDistance + fDeathSceneNoiseDistance) ) { React(); // Record the stimulus position m_vStimulusPosition = pDeathScene->GetPosition(); return LTTRUE; } } // Gotta check the pain noise too (using same criterion as pain noise) if ( g_pLTServer->GetTime() > pDeathScene->GetLastPainTime() && g_pLTServer->GetTime() < pDeathScene->GetLastPainTime() + 1.0f ) { // LastPain has to be within audible radius LTFLOAT fDistance = VEC_DIST(pDeathScene->GetPosition(), m_pAI->GetPosition()); LTFLOAT fPainNoiseDistance = g_pAIButeMgr->GetSenses()->fAllyPainNoiseDistance; fPainNoiseDistance *= pDeathScene->GetLastPainVolume(); if ( fDistance < (m_fDistance + fPainNoiseDistance) ) { return LTTRUE; } } return LTFALSE; }
/// Visit an element. virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* attribute) { if(element.ValueStr() == "world") { if(element.Parent() != element.GetDocument()) return false; return true; } else if(element.ValueStr() == "materials") { return true; } else if(element.ValueStr() == "material") { return true; } else if(element.ValueStr() == "bodies") { if(element.Parent()->ValueStr() != "world") return false; return true; } else if(element.ValueStr() == "ground") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); m_curBody = new World::Ground(); return true; } else if(element.ValueStr() == "box") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); double hx = 0.5; double hy = 0.5; double hz = 0.5; element.Attribute("hx", &hx); element.Attribute("hy", &hy); element.Attribute("hz", &hz); World::Cube* cube = new World::Cube(); cube->hx = hx; cube->hy = hy; cube->hz = hz; m_curBody = cube; return true; } else if(element.ValueStr() == "sphere") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); double r = 1; element.Attribute("r", &r); World::Sphere* sphere = new World::Sphere(); sphere->r = r; m_curBody = sphere; return true; } else if(element.ValueStr() == "cylinder") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); double r = 1; double startx, starty, startz; double endx, endy, endz; element.Attribute("r", &r); element.Attribute("sx", &startx); element.Attribute("sy", &starty); element.Attribute("sz", &startz); element.Attribute("ex", &endx); element.Attribute("ey", &endy); element.Attribute("ez", &endz); World::Cylinder* cylinder = new World::Cylinder(); cylinder->start = vec3(startx, starty, startz); cylinder->end = vec3(endx, endy, endz); cylinder->r = r; m_curBody = cylinder; return true; } else if(element.ValueStr() == "pos") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); double x = 0; double y = 0; double z = 0; element.Attribute("x", &x); element.Attribute("y", &y); element.Attribute("z", &z); m_curBody->pos = vec3(float(x), float(y), float(z)); return true; } else if(element.ValueStr() == "vel") { return false; } else if(element.ValueStr() == "ori") { return false; } else if(element.ValueStr() == "avel") { return false; } else if(element.ValueStr() == "bodymaterial") { return false; } else { return false; } assert(false); // we should never get here return false; }
Promise *DeRefCopyPromise(EvalContext *ctx, const Promise *pp) { Promise *pcopy; Rval returnval; pcopy = xcalloc(1, sizeof(Promise)); if (pp->promiser) { pcopy->promiser = xstrdup(pp->promiser); } if (pp->promisee.item) { pcopy->promisee = RvalCopy(pp->promisee); if (pcopy->promisee.type == RVAL_TYPE_LIST) { Rlist *rval_list = RvalRlistValue(pcopy->promisee); RlistFlatten(ctx, &rval_list); pcopy->promisee.item = rval_list; } } if (pp->classes) { pcopy->classes = xstrdup(pp->classes); } /* FIXME: may it happen? */ if ((pp->promisee.item != NULL && pcopy->promisee.item == NULL)) { ProgrammingError("Unable to copy promise"); } pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->has_subbundles = pp->has_subbundles; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; pcopy->offset = pp->offset; /* No further type checking should be necessary here, already done by CheckConstraintTypeMatch */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); Body *bp = NULL; FnCall *fp = NULL; /* A body template reference could look like a scalar or fn to the parser w/w () */ const Policy *policy = PolicyFromPromise(pp); Seq *bodies = policy ? policy->bodies : NULL; char body_ns[CF_MAXVARSIZE] = ""; char body_name[CF_MAXVARSIZE] = ""; switch (cp->rval.type) { case RVAL_TYPE_SCALAR: if (cp->references_body) { SplitScopeName(RvalScalarValue(cp->rval), body_ns, body_name); if (EmptyString(body_ns)) { strncpy(body_ns, PromiseGetNamespace(pp), CF_MAXVARSIZE); } bp = IsBody(bodies, body_ns, body_name); } fp = NULL; break; case RVAL_TYPE_FNCALL: fp = RvalFnCallValue(cp->rval); SplitScopeName(fp->name, body_ns, body_name); if (EmptyString(body_ns)) { strncpy(body_ns, PromiseGetNamespace(pp), CF_MAXVARSIZE); } bp = IsBody(bodies, body_ns, body_name); break; default: bp = NULL; fp = NULL; break; } /* First case is: we have a body template to expand lval = body(args), .. */ if (bp) { EvalContextStackPushBodyFrame(ctx, pcopy, bp, fp ? fp->args : NULL); if (strcmp(bp->type, cp->lval) != 0) { Log(LOG_LEVEL_ERR, "Body type mismatch for body reference '%s' in promise at line %zu of file '%s', '%s' does not equal '%s'", body_name, pp->offset.line, PromiseGetBundle(pp)->source_path, bp->type, cp->lval); } /* Keep the referent body type as a boolean for convenience when checking later */ if (IsDefinedClass(ctx, cp->classes, PromiseGetNamespace(pcopy))) { Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, (Rval) {xstrdup("true"), RVAL_TYPE_SCALAR }, false); cp_copy->offset = cp->offset; } if (bp->args != NULL) { /* There are arguments to insert */ if (fp == NULL || fp->args == NULL) { Log(LOG_LEVEL_ERR, "Argument mismatch for body reference '%s' in promise at line %zu of file '%s'", body_name, pp->offset.line, PromiseGetBundle(pp)->source_path); } for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); returnval = ExpandPrivateRval(ctx, NULL, "body", scp->rval.item, scp->rval.type); if (IsDefinedClass(ctx, scp->classes, PromiseGetNamespace(pcopy))) { Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, returnval, false); scp_copy->offset = scp->offset; } } } else { /* No arguments to deal with or body undeclared */ if (fp != NULL) { Log(LOG_LEVEL_ERR, "An apparent body \"%s()\" was undeclared or could have incorrect args, but used in a promise near line %zu of %s (possible unquoted literal value)", body_name, pp->offset.line, PromiseGetBundle(pp)->source_path); } else { for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); Rval newrv = RvalCopy(scp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } if (IsDefinedClass(ctx, scp->classes, PromiseGetNamespace(pcopy))) { Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, newrv, false); scp_copy->offset = scp->offset; } } } } EvalContextStackPopFrame(ctx); } else { const Policy *policy = PolicyFromPromise(pp); if (cp->references_body && !IsBundle(policy->bundles, EmptyString(body_ns) ? NULL : body_ns, body_name)) { Log(LOG_LEVEL_ERR, "Apparent body \"%s()\" was undeclared, but used in a promise near line %zu of %s (possible unquoted literal value)", body_name, pp->offset.line, PromiseGetBundle(pp)->source_path); } Rval newrv = RvalCopy(cp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } if (IsDefinedClass(ctx, cp->classes, PromiseGetNamespace(pcopy))) { Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, newrv, false); cp_copy->offset = cp->offset; } } } return pcopy; }
void ShowPromiseInReport(const char *version, Promise *pp, int indent) { Constraint *cp; Body *bp; Rlist *rp; FnCall *fp; fprintf(FREPORT_HTML, "%s\n", CFH[cfx_line][cfb]); fprintf(FREPORT_HTML, "%s\n", CFH[cfx_promise][cfb]); fprintf(FREPORT_HTML, "Promise type is %s%s%s, ", CFH[cfx_subtype][cfb], pp->agentsubtype, CFH[cfx_subtype][cfe]); fprintf(FREPORT_HTML, "<a href=\"#class_context\">context</a> is %s%s%s <br><hr>\n\n", CFH[cfx_class][cfb], pp->classes, CFH[cfx_class][cfe]); if (pp->promisee.item) { fprintf(FREPORT_HTML, "Resource object %s\'%s\'%s promises %s (about %s) to", CFH[cfx_object][cfb], pp->promiser, CFH[cfx_object][cfe], CFH[cfx_object][cfb], pp->agentsubtype); ShowRval(FREPORT_HTML, pp->promisee); fprintf(FREPORT_HTML, "%s\n\n", CFH[cfx_object][cfe]); } else { fprintf(FREPORT_HTML, "Resource object %s\'%s\'%s make the promise to default promisee 'cf-%s' (about %s)...\n\n", CFH[cfx_object][cfb], pp->promiser, CFH[cfx_object][cfe], pp->bundletype, pp->agentsubtype); } Indent(indent); if (pp->promisee.item != NULL) { fprintf(FREPORT_TXT, "%s promise by \'%s\' -> ", pp->agentsubtype, pp->promiser); ShowRval(FREPORT_TXT, pp->promisee); fprintf(FREPORT_TXT, " if context is %s\n\n", pp->classes); } else { fprintf(FREPORT_TXT, "%s promise by \'%s\' (implicit) if context is %s\n\n", pp->agentsubtype, pp->promiser, pp->classes); } for (cp = pp->conlist; cp != NULL; cp = cp->next) { fprintf(FREPORT_HTML, "%s%s%s => ", CFH[cfx_lval][cfb], cp->lval, CFH[cfx_lval][cfe]); Indent(indent + 3); fprintf(FREPORT_TXT, "%10s => ", cp->lval); switch (cp->rval.rtype) { case CF_SCALAR: if ((bp = IsBody(BODIES, (char *) cp->rval.item))) { ShowBody(bp, 15); } else { fprintf(FREPORT_HTML, "%s", CFH[cfx_rval][cfb]); ShowRval(FREPORT_HTML, cp->rval); /* literal */ fprintf(FREPORT_HTML, "%s", CFH[cfx_rval][cfe]); ShowRval(FREPORT_TXT, cp->rval); /* literal */ } break; case CF_LIST: rp = (Rlist *) cp->rval.item; fprintf(FREPORT_HTML, "%s", CFH[cfx_rval][cfb]); ShowRlist(FREPORT_HTML, rp); fprintf(FREPORT_HTML, "%s", CFH[cfx_rval][cfe]); ShowRlist(FREPORT_TXT, rp); break; case CF_FNCALL: fp = (FnCall *) cp->rval.item; if ((bp = IsBody(BODIES, fp->name))) { ShowBody(bp, 15); } else { ShowRval(FREPORT_HTML, cp->rval); /* literal */ ShowRval(FREPORT_TXT, cp->rval); /* literal */ } break; } if (cp->rval.rtype != CF_FNCALL) { Indent(indent); fprintf(FREPORT_HTML, " , if body <a href=\"#class_context\">context</a> <span class=\"context\">%s</span>\n", cp->classes); fprintf(FREPORT_TXT, " if body context %s\n", cp->classes); } } if (pp->audit) { Indent(indent); fprintf(FREPORT_HTML, "<p><small>Promise (version %s) belongs to bundle <b>%s</b> (type %s) in \'<i>%s</i>\' near line %zu</small></p>\n", version, pp->bundle, pp->bundletype, pp->audit->filename, pp->offset.line); } fprintf(FREPORT_HTML, "%s\n", CFH[cfx_promise][cfe]); fprintf(FREPORT_HTML, "%s\n", CFH[cfx_line][cfe]); if (pp->audit) { Indent(indent); fprintf(FREPORT_TXT, "Promise (version %s) belongs to bundle \'%s\' (type %s) in file \'%s\' near line %zu\n", version, pp->bundle, pp->bundletype, pp->audit->filename, pp->offset.line); fprintf(FREPORT_TXT, "\n\n"); } else { Indent(indent); fprintf(FREPORT_TXT, "Promise (version %s) belongs to bundle \'%s\' (type %s) near line %zu\n\n", version, pp->bundle, pp->bundletype, pp->offset.line); } }
/// Visit an element. virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* attribute) { if(element.ValueStr() == "world") { if(element.Parent() != element.GetDocument()) return false; return true; } else if(element.ValueStr() == "materials") { if(element.Parent()->ValueStr() != "world") return false; return true; } else if(element.ValueStr() == "material") { if(element.Parent()->ValueStr() != "materials") return false; char const* name; double density = 1; double friction = 0; double restitution = 0; double cr = 0; double cg = 0; double cb = 0; name = element.Attribute("name"); if(!name) { return false; } element.Attribute("density", &density); element.Attribute("friction", &friction); element.Attribute("restitution", &restitution); element.Attribute("cr", &cr); element.Attribute("cg", &cg); element.Attribute("cb", &cb); // populate sound parameters double thickness; double youngsModulus; double fluidDamping; double viscoelasticDamping; element.Attribute("thickness", &thickness); element.Attribute("youngsModulus", &youngsModulus); element.Attribute("fluidDamping", &fluidDamping); element.Attribute("viscoelasticDamping", &viscoelasticDamping); // if any values are NULL then set them to the default thickness = thickness == NULL ? 0.1 : thickness; youngsModulus = youngsModulus == NULL ? 900 : youngsModulus; fluidDamping = fluidDamping == NULL ? 0.00001 : fluidDamping; viscoelasticDamping = viscoelasticDamping == NULL ? 0.1 : viscoelasticDamping; m_curMaterial = new Material(float(density), float(friction), float(restitution), Vector3(float(cr), float(cg), float(cb)), float(thickness), float(youngsModulus), float(fluidDamping), float(viscoelasticDamping)); m_materials[name] = m_curMaterial; return true; } else if(element.ValueStr() == "bodies") { if(element.Parent()->ValueStr() != "world") return false; return true; } else if(element.ValueStr() == "ground") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); m_curBody = new Ground(); return true; } else if(element.ValueStr() == "box") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); double hx = 1; double hy = 1; double hz = 1; element.Attribute("hx", &hx); element.Attribute("hy", &hy); element.Attribute("hz", &hz); m_curBody = new Box(Vector3(float(hx), float(hy), float(hz))); return true; } else if(element.ValueStr() == "sphere") { if(element.Parent()->ValueStr() != "bodies") return false; assert(m_curBody == NULL); double r = 1; element.Attribute("r", &r); m_curBody = new Sphere(float(r)); return true; } else if(element.ValueStr() == "id") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); int id = 0; element.Attribute("id", &id); m_curBody->SetID(id); return true; } else if(element.ValueStr() == "pos") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); double x = 0; double y = 0; double z = 0; element.Attribute("x", &x); element.Attribute("y", &y); element.Attribute("z", &z); m_curBody->SetPosition(Vector3(float(x), float(y), float(z))); return true; } else if(element.ValueStr() == "vel") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); double x = 0; double y = 0; double z = 0; element.Attribute("x", &x); element.Attribute("y", &y); element.Attribute("z", &z); m_curBody->SetVelocity(Vector3(float(x), float(y), float(z))); return true; } else if(element.ValueStr() == "ori") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); double theta = 0; double x = 0; double y = 0; double z = 0; element.Attribute("theta", &theta); element.Attribute("x", &x); element.Attribute("y", &y); element.Attribute("z", &z); m_curBody->SetOrientation(Quaternion(float(theta), Vector3(float(x), float(y), float(z)))); return true; } else if(element.ValueStr() == "avel") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); double x = 0; double y = 0; double z = 0; element.Attribute("x", &x); element.Attribute("y", &y); element.Attribute("z", &z); m_curBody->SetAngularVelocity(Vector3(float(x), float(y), float(z))); return true; } else if(element.ValueStr() == "bodymaterial") { if(!IsBody(element.Parent())) return false; assert(m_curBody != NULL); const char* name = element.Attribute("name"); Material* material = m_materials[name]; if(material != NULL) { m_curBody->SetMaterial(material); } return true; } else { return false; } assert(false); // we should never get here return false; }
LTBOOL DoVectorFilterFn(HOBJECT hObj, void *pUserData) { // We're not attacking our self... if (SpecificObjectFilterFn(hObj, pUserData)) { // CharacterHitBox objects are used for vector impacts, don't // impact on the character/body prop object itself.... if (IsCharacter(hObj) || IsBody(hObj) || IsKindOf(hObj, "Intelligence")) { return LTFALSE; } // Check special character hit box cases... if (IsCharacterHitBox(hObj)) { CCharacterHitBox *pCharHitBox = (CCharacterHitBox*) g_pLTServer->HandleToObject(hObj); if (pCharHitBox) { // Make sure we don't hit ourself... HOBJECT hUs = (HOBJECT)pUserData; HOBJECT hTestObj = pCharHitBox->GetModelObject(); if (!hTestObj) return LTFALSE; if (hTestObj == hUs) { return LTFALSE; } // Do special AI hitting AI case... if (IsAI(hUs) && IsAI(hTestObj)) { CAI *pAI = (CAI*) g_pLTServer->HandleToObject(hUs); if (!pAI) return LTFALSE; // We can't hit guys we like, unless they're NEUTRAL CCharacter* pB = (CCharacter*)g_pLTServer->HandleToObject(hTestObj); if (!pB) return LTFALSE; CharacterClass cc = pB->GetCharacterClass(); if (cc != NEUTRAL) { return LIKE != GetAlignement(pAI->GetCharacterClass(), cc); } } // Check for friendly fire if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && g_vtNetFriendlyFire.GetFloat() < 1.0f) { // We can't hit guys on our team unless friendly fire is turned on if (IsPlayer(hUs) && IsPlayer(hTestObj)) { CPlayerObj* pUs = (CPlayerObj*) g_pLTServer->HandleToObject(hUs); if (!pUs) return LTFALSE; CPlayerObj* pThem = (CPlayerObj*) g_pLTServer->HandleToObject(hTestObj); if (!pThem) return LTFALSE; if (pUs->GetTeamID() == pThem->GetTeamID()) return LTFALSE; } } } } return LTTRUE; } return LTFALSE; }
void CProjectile::HandleTouch(HOBJECT hObj) { if (m_bObjectRemoved) return; // Don't process any touches until this has been cleared... if (m_bProcessInvImpact) return; // Let it get out of our bounding box... if (hObj == m_hFiredFrom) return; CCharacterHitBox* pHitBox = LTNULL; // If we've hit a character (or body), let its hit box take control... if (IsCharacter(hObj)) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj); if (pChar) { hObj = pChar->GetHitBox(); } } else if (IsBody(hObj)) { Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); if (pBody) { hObj = pBody->GetHitBox(); } } if (IsCharacterHitBox(hObj)) { pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj); if (!pHitBox) return; if (pHitBox->GetModelObject() == m_hFiredFrom) return; } // Don't hit our own type of projectiles (for multi-projectile weapons // and projectiles that stick to objects)... if (IsKindOf(hObj, m_hObject)) { CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj); if (pObj) { if (pObj->GetFiredFrom() == m_hFiredFrom) { return; } } } // See if we want to impact on this object... uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj); if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return; LTBOOL bIsWorld = IsMainWorld(hObj); // Don't impact on non-solid objects...unless it is a CharacterHitBox // object... uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj); if (!bIsWorld && !(dwFlags & FLAG_SOLID)) { if (pHitBox) { // See if we really impacted on the box... if (pHitBox->DidProjectileImpact(this)) { // This is the object that we really hit... hObj = pHitBox->GetModelObject(); } else { return; } } else if (!(dwFlags & FLAG_RAYHIT)) { // If we have ray hit set to true, projectiles should // impact on us too... return; } } // See if we hit the sky... if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj))) { CollisionInfo info; g_pLTServer->GetLastCollision(&info); SurfaceType eType = GetSurfaceType(info); if (eType == ST_SKY) { RemoveObject(); return; } else if (eType == ST_INVISIBLE) { // Update 1.002 [KLS] - If multiplayer and we hit an invisible // surface, just treat it like a normal surface... if (!IsMultiplayerGame()) { m_bProcessInvImpact = LTTRUE; g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos); g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel); m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime()); // Make sure this new position is inside the world...else // just blow up... if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos)) { return; } } } } HandleImpact(hObj); }
static void VerifyPromises(enum cfagenttype agent) { struct Bundle *bp; struct SubType *sp; struct Promise *pp; struct Body *bdp; struct Rlist *rp; struct FnCall *fp; char *scope; if (REQUIRE_COMMENTS == CF_UNDEFINED) { for (bdp = BODIES; bdp != NULL; bdp = bdp->next) /* get schedule */ { if ((strcmp(bdp->name,"control") == 0) && (strcmp(bdp->type,"common") == 0)) { REQUIRE_COMMENTS = GetRawBooleanConstraint("require_comments",bdp->conlist); break; } } } for (rp = BODYPARTS; rp != NULL; rp=rp->next) { switch (rp->type) { case CF_SCALAR: if (!IsBody(BODIES,(char *)rp->item)) { CfOut(cf_error,"","Undeclared promise body \"%s()\" was referenced in a promise\n",(char *)rp->item); ERRORCOUNT++; } break; case CF_FNCALL: fp = (struct FnCall *)rp->item; if (!IsBody(BODIES,fp->name)) { CfOut(cf_error,"","Undeclared promise body \"%s()\" was referenced in a promise\n",fp->name); ERRORCOUNT++; } break; } } /* Check for undefined subbundles */ for (rp = SUBBUNDLES; rp != NULL; rp=rp->next) { switch (rp->type) { case CF_SCALAR: if (!IGNORE_MISSING_BUNDLES && !IsCf3VarString(rp->item) && !IsBundle(BUNDLES,(char *)rp->item)) { CfOut(cf_error,"","Undeclared promise bundle \"%s()\" was referenced in a promise\n",(char *)rp->item); ERRORCOUNT++; } break; case CF_FNCALL: fp = (struct FnCall *)rp->item; if (!IGNORE_MISSING_BUNDLES && !IsCf3VarString(fp->name) && !IsBundle(BUNDLES,fp->name)) { CfOut(cf_error,"","Undeclared promise bundle \"%s()\" was referenced in a promise\n",fp->name); ERRORCOUNT++; } break; } } /* Now look once through ALL the bundles themselves */ for (bp = BUNDLES; bp != NULL; bp = bp->next) /* get schedule */ { scope = bp->name; THIS_BUNDLE = bp->name; for (sp = bp->subtypes; sp != NULL; sp = sp->next) /* get schedule */ { if (strcmp(sp->name,"classes") == 0) { /* these should not be evaluated here */ if (agent != cf_common) { continue; } } for (pp = sp->promiselist; pp != NULL; pp=pp->next) { ExpandPromise(agent,scope,pp,NULL); } } } HashVariables(NULL); HashControls(); /* Now look once through the sequences bundles themselves */ if (VerifyBundleSequence(agent) == false) { FatalError("Errors in promise bundles"); } }
Promise *DeRefCopyPromise(EvalContext *ctx, const Promise *pp) { Promise *pcopy; Rval returnval; if (pp->promisee.item) { CfDebug("CopyPromise(%s->", pp->promiser); if (DEBUG) { RvalShow(stdout, pp->promisee); } CfDebug("\n"); } else { CfDebug("CopyPromise(%s->)\n", pp->promiser); } pcopy = xcalloc(1, sizeof(Promise)); if (pp->promiser) { pcopy->promiser = xstrdup(pp->promiser); } if (pp->promisee.item) { pcopy->promisee = RvalCopy(pp->promisee); if (pcopy->promisee.type == RVAL_TYPE_LIST) { Rlist *rval_list = RvalRlistValue(pcopy->promisee); RlistFlatten(ctx, &rval_list); pcopy->promisee.item = rval_list; } } if (pp->classes) { pcopy->classes = xstrdup(pp->classes); } /* FIXME: may it happen? */ if ((pp->promisee.item != NULL && pcopy->promisee.item == NULL)) { ProgrammingError("Unable to copy promise"); } pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->has_subbundles = pp->has_subbundles; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; pcopy->offset = pp->offset; CfDebug("Copying promise constraints\n\n"); /* No further type checking should be necessary here, already done by CheckConstraintTypeMatch */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); Body *bp = NULL; FnCall *fp = NULL; char *bodyname = NULL; /* A body template reference could look like a scalar or fn to the parser w/w () */ Policy *policy = PolicyFromPromise(pp); Seq *bodies = policy ? policy->bodies : NULL; switch (cp->rval.type) { case RVAL_TYPE_SCALAR: bodyname = (char *) cp->rval.item; if (cp->references_body) { bp = IsBody(bodies, PromiseGetNamespace(pp), bodyname); } fp = NULL; break; case RVAL_TYPE_FNCALL: fp = (FnCall *) cp->rval.item; bodyname = fp->name; bp = IsBody(bodies, PromiseGetNamespace(pp), bodyname); break; default: bp = NULL; fp = NULL; bodyname = NULL; break; } /* First case is: we have a body template to expand lval = body(args), .. */ if (bp) { EvalContextStackPushBodyFrame(ctx, bp); if (strcmp(bp->type, cp->lval) != 0) { Log(LOG_LEVEL_ERR, "Body type mismatch for body reference \"%s\" in promise at line %zu of %s (%s != %s)\n", bodyname, pp->offset.line, PromiseGetBundle(pp)->source_path, bp->type, cp->lval); } /* Keep the referent body type as a boolean for convenience when checking later */ { Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, (Rval) {xstrdup("true"), RVAL_TYPE_SCALAR }, cp->classes, false); cp_copy->offset = cp->offset; } CfDebug("Handling body-lval \"%s\"\n", cp->lval); if (bp->args != NULL) { /* There are arguments to insert */ if (fp == NULL || fp->args == NULL) { Log(LOG_LEVEL_ERR, "Argument mismatch for body reference \"%s\" in promise at line %zu of %s", bodyname, pp->offset.line, PromiseGetBundle(pp)->source_path); } if (fp && bp && fp->args && bp->args && !ScopeMapBodyArgs(ctx, "body", fp->args, bp->args)) { Log(LOG_LEVEL_ERR, "Number of arguments does not match for body reference \"%s\" in promise at line %zu of %s\n", bodyname, pp->offset.line, PromiseGetBundle(pp)->source_path); } for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); CfDebug("Doing arg-mapped sublval = %s (promises.c)\n", scp->lval); returnval = ExpandPrivateRval(ctx, "body", scp->rval); { Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, returnval, scp->classes, false); scp_copy->offset = scp->offset; } } ScopeClear("body"); } else { /* No arguments to deal with or body undeclared */ if (fp != NULL) { Log(LOG_LEVEL_ERR, "An apparent body \"%s()\" was undeclared or could have incorrect args, but used in a promise near line %zu of %s (possible unquoted literal value)", bodyname, pp->offset.line, PromiseGetBundle(pp)->source_path); } else { for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); CfDebug("Doing sublval = %s (promises.c)\n", scp->lval); Rval newrv = RvalCopy(scp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } { Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, newrv, scp->classes, false); scp_copy->offset = scp->offset; } } } } EvalContextStackPopFrame(ctx); } else { Policy *policy = PolicyFromPromise(pp); if (cp->references_body && !IsBundle(policy->bundles, bodyname)) { Log(LOG_LEVEL_ERR, "Apparent body \"%s()\" was undeclared, but used in a promise near line %zu of %s (possible unquoted literal value)", bodyname, pp->offset.line, PromiseGetBundle(pp)->source_path); } Rval newrv = RvalCopy(cp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } { Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, newrv, cp->classes, false); cp_copy->offset = cp->offset; } } } return pcopy; }
void CSpear::HandleImpact(HOBJECT hObj) { if (!g_vtSpearStickPercentage.IsInitted()) { g_vtSpearStickPercentage.Init(g_pLTServer, "SpearStickPercent", LTNULL, 0.9f); } if (!m_pAmmoData || !m_pAmmoData->pProjectileFX) { CProjectile::HandleImpact(hObj); return; } CollisionInfo info; g_pLTServer->GetLastCollision(&info); LTVector vPos, vVel, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); // Should we break the spear? enum SpearAction { eSpearActionBreak, eSpearActionStickWorld, eSpearActionStickAI, eSpearActionStickPlayer, eSpearActionStickBody }; SpearAction eSpearAction = eSpearActionBreak; // Randomly break even if we could sometimes stick... if (GetRandom(0.0, 1.0f) > g_vtSpearStickPercentage.GetFloat()) { eSpearAction = eSpearActionBreak; } else if (IsMainWorld(hObj)) { // Calculate where we really hit the world... g_pLTServer->GetVelocity(m_hObject, &vVel); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT(info.m_Plane.m_Normal, vP0) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(info.m_Plane.m_Normal, vP1) - info.m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos(m_hObject, &vPos); eSpearAction = eSpearActionStickWorld; } else if (IsMoveable(hObj)) { if (IsAI(hObj)) { // Attach to a AI eSpearAction = eSpearActionStickAI; } else if (IsPlayer(hObj)) { // Attach to a Player eSpearAction = eSpearActionStickPlayer; } else if (IsBody(hObj)) { // Attach to a body eSpearAction = eSpearActionStickBody; } else { // Could probably come up with a way to attach to moveable // non-character objects (like doors), but it is much easier // to just break it ;)... eSpearAction = eSpearActionBreak; } } // If the surface is too hard, the spear will just break when // it hits it... SurfaceType eSurf = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurf); if ((eSpearActionBreak == eSpearAction) || ((eSpearActionStickWorld == eSpearAction) && pSurf && pSurf->fHardness > 0.5)) { // Create spear debris... DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_pAmmoData->szName); if (pDebris) { vVel.Norm(); LTVector vNegVel = -vVel; CreatePropDebris(vPos, vNegVel, pDebris->nId); } CProjectile::HandleImpact(hObj); return; } // Create the Spear powerup... char szSpawn[512]; sprintf(szSpawn, "AmmoBox AmmoType1 %s;AmmoCount1 1;Filename %s;Skin %s", m_pAmmoData->szName, m_pAmmoData->pProjectileFX->szModel, m_pAmmoData->pProjectileFX->szSkin); LTVector vScale = m_pAmmoData->pProjectileFX->vModelScale; // Make sure the spear sticks out a little ways... vVel.Norm(); vPos -= (vVel * vScale.z/2.0f); if (eSpearActionStickWorld == eSpearAction) { g_pLTServer->AlignRotation(&rRot, &vVel, LTNULL); } BaseClass* pClass = SpawnObject(szSpawn, LTVector(-10000,-10000,-10000), rRot); if (pClass) { g_pLTServer->ScaleObject(pClass->m_hObject, &vScale); LTVector vDims; g_pLTServer->GetObjectDims(pClass->m_hObject, &vDims); vDims.x *= vScale.x; vDims.y *= vScale.y; vDims.z *= vScale.z; g_pLTServer->SetObjectDims(pClass->m_hObject, &vDims); // We don't want other projectiles to impact on us... //uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(pClass->m_hObject); //dwUsrFlags |= USRFLG_IGNORE_PROJECTILES; //g_pLTServer->SetObjectUserFlags(pClass->m_hObject, dwUsrFlags); if ( eSpearActionStickAI == eSpearAction || eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); if ( eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) | USRFLG_ATTACH_HIDE1SHOW3); } // Attach it to the character CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hObj); pCharacter->AddSpear(pClass->m_hObject, pCharacter->GetModelNodeLastHit(), rRot); } else if ( eSpearActionStickBody == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); // Attach it to the body Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); pBody->AddSpear(pClass->m_hObject, rRot); } else // ( eSpearActionStickWorld == eSpearAction ) { // Move it to the right position in the world g_pLTServer->SetObjectPos(pClass->m_hObject, &vPos); } } CProjectile::HandleImpact(hObj); }