/* returns actors that match the [x.y.z] expression */ static Targets* EvaluateObject(Map *map, Scriptable* Sender, Object* oC, int ga_flags) { // if you ActionOverride a global actor, they might not have a map :( // TODO: don't allow this to happen? if (!map) { return NULL; } if (oC->objectName[0]) { //We want the object by its name... (doors/triggers don't play here!) Actor* aC = map->GetActor( oC->objectName, ga_flags ); /*if (!aC && (ga_flags&GA_GLOBAL) ) { aC = FindActorNearby(oC->objectName, map, ga_flags ); }*/ //return here because object name/IDS targeting are mutually exclusive return ReturnActorAsTarget(aC); } if (oC->objectFields[0]==-1) { // this is an internal hack, allowing us to pass actor ids around as objects Actor* aC = map->GetActorByGlobalID( (ieDword) oC->objectFields[1] ); /* TODO: this hack will throw away an invalid target */ /* Consider putting this in GetActorByGlobalID */ if (aC && !aC->ValidTarget(ga_flags)) { aC = NULL; } return ReturnActorAsTarget(aC); } Targets *tgts = NULL; //we need to get a subset of actors from the large array //if this gets slow, we will need some index tables int i = map->GetActorCount(true); while (i--) { Actor *ac = map->GetActor(i, true); if (!ac) continue; // is this check really needed? // don't return Sender in IDS targeting! if (ac == Sender) continue; bool filtered = false; if (DoObjectIDSCheck(oC, ac, &filtered)) { if (!filtered) { // if no filters were applied.. assert(!tgts); return NULL; } int dist; if (DoObjectChecks(map, Sender, ac, dist, (ga_flags & GA_DETECT) != 0)) { if (!tgts) tgts = new Targets(); tgts->AddTarget((Scriptable *) ac, dist, ga_flags); } } } return tgts; }
bool MatchActor(Scriptable *Sender, ieDword actorID, Object* oC) { if (!Sender) { return false; } Actor *ac = Sender->GetCurrentArea()->GetActorByGlobalID(actorID); if (!ac) { return false; } // [0]/[ANYONE] can match all actors if (!oC) { return true; } bool filtered = false; // name matching if (oC->objectName[0]) { if (strnicmp(ac->GetScriptName(), oC->objectName, 32) != 0) { return false; } filtered = true; } // IDS targeting // (if we already matched by name, we don't do this) // TODO: check distance? area? visibility? if (!filtered && !DoObjectIDSCheck(oC, ac, &filtered)) return false; // globalID hack should never get here assert(oC->objectFilters[0] != -1); // object filters if (oC->objectFilters[0]) { // object filters insist on having a stupid targets list, // so we waste a lot of time here Targets *tgts = new Targets(); int ga_flags = 0; // TODO: correct? // handle already-filtered vs not-yet-filtered cases // e.g. LastTalkedToBy(Myself) vs LastTalkedToBy if (filtered) tgts->AddTarget(ac, 0, ga_flags); tgts = DoObjectFiltering(Sender, tgts, oC, ga_flags); if (!tgts) return false; // and sometimes object filters are lazy and not only don't filter // what we give them, they clear it and return a list :( // so we have to search the whole list.. bool ret = false; targetlist::iterator m; const targettype *tt = tgts->GetFirstTarget(m, ST_ACTOR); while (tt) { Actor *actor = (Actor *) tt->actor; if (actor->GetGlobalID() == actorID) { ret = true; break; } tt = tgts->GetNextTarget(m, ST_ACTOR); } delete tgts; if (!ret) return false; } return true; }
/* returns actors that match the [x.y.z] expression */ static Targets* EvaluateObject(Map *map, Scriptable* Sender, Object* oC, int ga_flags) { // if you ActionOverride a global actor, they might not have a map :( // TODO: don't allow this to happen? if (!map) { return NULL; } if (oC->objectName[0]) { //We want the object by its name... Scriptable* aC = map->GetActor( oC->objectName, ga_flags ); /*if (!aC && (ga_flags&GA_GLOBAL) ) { aC = FindActorNearby(oC->objectName, map, ga_flags ); }*/ //This order is the same as in GetActorObject //TODO:merge them if (!aC) { aC = map->GetTileMap()->GetDoor(oC->objectName); } if (!aC) { aC = map->GetTileMap()->GetContainer(oC->objectName); } if (!aC) { aC = map->GetTileMap()->GetInfoPoint(oC->objectName); } //return here because object name/IDS targeting are mutually exclusive return ReturnScriptableAsTarget(aC); } if (oC->objectFields[0]==-1) { // this is an internal hack, allowing us to pass actor ids around as objects Actor* aC = map->GetActorByGlobalID( (ieDword) oC->objectFields[1] ); if (aC) { if (!aC->ValidTarget(ga_flags)) { return NULL; } return ReturnScriptableAsTarget(aC); } Door *door = map->GetDoorByGlobalID( (ieDword) oC->objectFields[1]); if (door) { return ReturnScriptableAsTarget(door); } Container* cont = map->GetContainerByGlobalID((ieDword) oC->objectFields[1]); if (cont) { return ReturnScriptableAsTarget(cont); } InfoPoint* trap = map->GetInfoPointByGlobalID((ieDword) oC->objectFields[1]); if (trap) { return ReturnScriptableAsTarget(trap); } return NULL; } Targets *tgts = NULL; //we need to get a subset of actors from the large array //if this gets slow, we will need some index tables int i = map->GetActorCount(true); while (i--) { Actor *ac = map->GetActor(i, true); if (!ac) continue; // is this check really needed? // don't return Sender in IDS targeting! if (ac == Sender) continue; bool filtered = false; if (DoObjectIDSCheck(oC, ac, &filtered)) { // this is needed so eg. Range trigger gets a good object // HACK: our parsing of Attack([0]) is broken if (!filtered) { // if no filters were applied.. assert(!tgts); return NULL; } int dist; if (DoObjectChecks(map, Sender, ac, dist, (ga_flags & GA_DETECT) != 0)) { if (!tgts) tgts = new Targets(); tgts->AddTarget((Scriptable *) ac, dist, ga_flags); } } } return tgts; }