diff options
author | Walter van Niftrik | 2009-03-27 23:01:13 +0000 |
---|---|---|
committer | Walter van Niftrik | 2009-03-27 23:01:13 +0000 |
commit | e860473d80a7f3235b3db6014194b64a2f0990d1 (patch) | |
tree | 6776e3e85337035b2d4e6a4c5e321e31289a101f /engines/sci/engine | |
parent | ce414e66719161461367f6ec065f61b1ac42248a (diff) | |
download | scummvm-rg350-e860473d80a7f3235b3db6014194b64a2f0990d1.tar.gz scummvm-rg350-e860473d80a7f3235b3db6014194b64a2f0990d1.tar.bz2 scummvm-rg350-e860473d80a7f3235b3db6014194b64a2f0990d1.zip |
SCI: AvoidPath workaround for intersecting polygons in Longbow, room 210.
svn-id: r39714
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/kpathing.cpp | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 5c0c4bcfa3..b5f4a90b13 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -126,6 +126,17 @@ public: typedef Common::List<Vertex *> VertexList; +/* Circular list definitions. */ + +#define CLIST_FOREACH(var, head) \ + for ((var) = (head)->first(); \ + (var); \ + (var) = ((var)->_next == (head)->first() ? \ + NULL : (var)->_next)) + +/* Circular list access methods. */ +#define CLIST_NEXT(elm) ((elm)->_next) +#define CLIST_PREV(elm) ((elm)->_prev) class CircularVertexList { public: @@ -134,7 +145,7 @@ public: public: CircularVertexList() : _head(0) {} - Vertex *first() { + Vertex *first() const { return _head; } @@ -172,6 +183,14 @@ public: return _head == NULL; } + uint size() const { + int n = 0; + Vertex *v; + CLIST_FOREACH(v, this) + ++n; + return n; + } + /** * Reverse the order of the elements in this circular list. */ @@ -187,19 +206,6 @@ public: } }; -/* Circular list definitions. */ - -#define CLIST_FOREACH(var, head) \ - for ((var) = (head)->first(); \ - (var); \ - (var) = ((var)->_next == (head)->first() ? \ - NULL : (var)->_next)) - -/* Circular list access methods. */ -#define CLIST_NEXT(elm) ((elm)->_next) -#define CLIST_PREV(elm) ((elm)->_prev) - - struct Polygon { // SCI polygon type int type; @@ -1217,6 +1223,56 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { return poly; } +// WORKAROUND: intersecting polygons in Longbow, room 210. +static void fixLongbowRoom210(PathfindingState *s, const Common::Point &start, const Common::Point &end) { + Polygon *barred = NULL; + Polygon *total = NULL; + + // Find the intersecting polygons + for (PolygonList::iterator it = s->polygons.begin(); it != s->polygons.end(); ++it) { + Polygon *polygon = *it; + assert(polygon); + + if ((polygon->type == POLY_BARRED_ACCESS) && (polygon->vertices.size() == 11) + && (polygon->vertices.first()->v == Common::Point(319, 161))) + barred = polygon; + else if ((polygon->type == POLY_TOTAL_ACCESS) && (polygon->vertices.size() == 8) + && (polygon->vertices.first()->v == Common::Point(313, 58))) + total = polygon; + } + + if (!barred || !total) + return; + + debug(1, "[avoidpath] Applying fix for intersecting polygons in Longbow, room 210"); + + // If the start or end point is contained in the total access polygon, removing that + // polygon is sufficient. Otherwise we merge the total and barred access polygons. + bool both_outside = (contained(start, total) == CONT_OUTSIDE) && (contained(end, total) == CONT_OUTSIDE); + + s->polygons.remove(total); + delete total; + + if (both_outside) { + int points[28] = { + 224, 159, 223, 162 ,194, 173 ,107, 173, 74, 162, 67, 156, 2, 58, + 63, 160, 0, 160, 0, 0, 319, 0, 319, 161, 228, 161, 313, 58 + }; + + s->polygons.remove(barred); + delete barred; + + barred = new Polygon(POLY_BARRED_ACCESS); + + for (int i = 0; i < 14; i++) { + Vertex *vertex = new Vertex(Common::Point(points[i * 2], points[i * 2 + 1])); + barred->vertices.insertHead(vertex); + } + + s->polygons.push_front(barred); + } +} + static void change_polygons_opt_0(PathfindingState *s) { // Changes the polygon list for optimization level 0 (used for keyboard // support). Totally accessible polygons are removed and near-point @@ -1275,7 +1331,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co if (dup == node) { // Polygon is not a duplicate, so convert it polygon = convert_polygon(s, node->value); - pf_s->polygons.push_front(polygon); + pf_s->polygons.push_back(polygon); count += KP_UINT(GET_SEL32(node->value, size)); } @@ -1321,6 +1377,12 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co pf_s->_appendPoint = new Common::Point(end); } + if (s->_gameName == "Longbow") { + // FIXME: implement function to get current room number + if ((KP_UINT(s->script_000->locals_block->locals[13]) == 210)) + fixLongbowRoom210(pf_s, new_start, new_end); + } + // Merge start and end points into polygon set pf_s->vertex_start = merge_point(pf_s, new_start); pf_s->vertex_end = merge_point(pf_s, new_end); |