summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-02-06 21:12:36 +0100
committerHaru <haru@dotalux.com>2014-03-05 22:35:03 +0100
commita1918e7e9d1585587be270183866797eb1c682f5 (patch)
treed07b30baaed8a40778c2510b5a112838eb1da7e5
parent4f3156b78f807553b11f37a7d0c898f6e358495b (diff)
downloadhercules-a1918e7e9d1585587be270183866797eb1c682f5.tar.gz
hercules-a1918e7e9d1585587be270183866797eb1c682f5.tar.bz2
hercules-a1918e7e9d1585587be270183866797eb1c682f5.tar.xz
hercules-a1918e7e9d1585587be270183866797eb1c682f5.zip
Corrected same-reference check to work on vars with the same name in different scopes
- Fixes bugreport:8008, special thanks to KeyWorld http://hercules.ws/board/tracker/issue-8008-copyarray-fail-on-a-referenced-array-argument/ Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/script.c25
-rw-r--r--src/map/script.h7
2 files changed, 18 insertions, 14 deletions
diff --git a/src/map/script.c b/src/map/script.c
index bf6dd448a..bef5f37e0 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -5770,30 +5770,27 @@ BUILDIN(copyarray)
count = script_getnum(st, 4);
if( count > SCRIPT_MAX_ARRAYSIZE - idx1 )
count = SCRIPT_MAX_ARRAYSIZE - idx1;
- if( count <= 0 || (id1 == id2 && idx1 == idx2) )
+ if( count <= 0 || (idx1 == idx2 && is_same_reference(data1, data2)) )
return true;// nothing to copy
- if( id1 == id2 && idx1 > idx2 )
- {// destination might be overlapping the source - copy in reverse order
- for( i = count - 1; i >= 0; --i )
- {
+ if( is_same_reference(data1, data2) && idx1 > idx2 ) {
+ // destination might be overlapping the source - copy in reverse order
+ for( i = count - 1; i >= 0; --i ) {
v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
script_removetop(st, -1, 0);
}
- }
- else
- {// normal copy
- for( i = 0; i < count; ++i )
- {
- if( idx2 + i < SCRIPT_MAX_ARRAYSIZE )
- {
+ } else {
+ // normal copy
+ for( i = 0; i < count; ++i ) {
+ if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) {
v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
script_removetop(st, -1, 0);
- }
- else// out of range - assume ""/0
+ } else {
+ // out of range - assume ""/0
script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1));
+ }
}
}
return true;
diff --git a/src/map/script.h b/src/map/script.h
index ae851a7ec..ff947bf79 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -144,6 +144,13 @@ struct eri;
/// Composes the uid of a reference from the id and the index
#define reference_uid(id,idx) ( (int64) ((uint64)(id) & 0xFFFFFFFF) | ((uint64)(idx) << 32) )
+/// Checks whether two references point to the same variable (or array)
+#define is_same_reference(data1, data2) \
+ ( reference_getid(data1) == reference_getid(data2) \
+ && ( (data1->ref == data2->ref && data1->ref == NULL) \
+ || (data1->ref != NULL && data2->ref != NULL && data1->ref->vars == data2->ref->vars \
+ ) ) )
+
#define script_getvarid(var) ( (int32)(int64)(var & 0xFFFFFFFF) )
#define script_getvaridx(var) ( (uint32)(int64)((var >> 32) & 0xFFFFFFFF) )