Вопрос трабл с итерацией

Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
326
Реакции[?]
24
Поинты[?]
12K
После использованием санстрайка(котороя создает объект C_DOTA_BaseNPC) для thinker'a я сдампил все сущности ( от 0 до HighestEntIndex )

но странная штука произошла:

C++:
#Начало, тоесть сразу после использования санстрайка
Searching for entities with class/target name containing substring: 'thinker'
   'npc_dota_thinker' : 'npc_dota_thinker' (entindex 280) 
Found 1 matches.

0 ) worldent
....

264 ) item_tpscroll
и всё, здесь конец.
эти числа это индексы(не loop i )
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
326
Реакции[?]
24
Поинты[?]
12K
оффсеты дважды перепроверь везде
инфы больше скинь, как итерируешь и тд и тп
C++:
 int i = 0;

                for (C_BaseEntity* entity = EntitySystem->GetBaseEntity(i); i < EntitySystem->GetHighestEntityIndex(); entity = EntitySystem->GetBaseEntity(i++))
                ConsoleMessage("%d )  %s\n", entity->GetIndex(), entity->GetName());
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
ну во-первых
for (C_BaseEntity* entity = EntitySystem->GetBaseEntity(i); i < EntitySystem->GetHighestEntityIndex(); entity = EntitySystem->GetBaseEntity(i++))
пофикси свой i++.
ты получашеь дважды первую сущность изза того что у тебя i++ там а не ++i. i++ это значит "создать копию i, увеличить оригинальный i на один, вернуть копию i(которая до модификации была)". то есть старое значение i возвращает до увеличения. то есть
i = 0;
shit(i++);
это эквивалентно
i = 0;
shit(i);//shit(0) в данном случае
i++;
во-вторых
чек бы на нуллптр(entity != nullptr) еще бы добавить) раз у тебя указатель то чекай на ноль
это так для разминки
ну и не i < highest; а i <= highest. высочайший это последний валидный(а не количество сущностей). он равен -1 когда нет сущностей, а когда они есть представляет собой индекс последней валидной сущности.
а так вроде все нормально. если в твоем говне фиксануть инкремент на ++i и переделать < в <= то вроде все нормально.
но конечно же энтитей так не итерируют. сделай себе хотя бы рейндж простейший который за тебя под колпаком этой фигней будет заниматься(и будет скипать нуллптр сущности и референс возвращать. правда это уже не совсем простейший рейндж будет xD), и итерируй
for(C_BaseEntity& entity : EntitySystem->GetEntities())
в общем на с++ пиши брат а не на с
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
вот например как можно бы сделать(ниже proof-of-concept код, чисто ПОКАЗАТЕЛЬНЫЙ, имеющий цель просто показать как твой код МОГ БЫ ВЫГЛЯДЕТЬ. код ниже не тестирован должным образом(мне лень), НЕ КОПИПАСТЬ. здесь полюбас миллион багов потому что Я НЕ ТЕСТИЛ ОСОБО. данный код подлежит ревизиям и модификациям. берешь создаешь новый проект, создаешь модель(модель - новый объект, отражающий интересующие свойства оригинального объекта. в нашем случае свойства интересующие нас это то что есть highest_index, что есть вместимость системы(32768), что у нас 512 листов по 64 сущности, могут быть нуллптр сущности(их скипаем при итерации), блаблабла) энтитисистемы и тестишь там самые различные варианты. например где самая первая сущность нуллптр, где последняя сущность нуллптр, где максимум сущностей, где нет сущностей, где еще чето блаблабла ЭТО НАДО СДЕЛАТЬ ЧТОБЫ БЫТЬ УВЕРЕННЫМ ЧТО ВСЕ АХУЕННО, без этого нельзя абсолютно нихуя утверждать о корректности кода. поэтому я и не говорю что код ниже валидный. я наоборот говорю что он хуита потому что я не тестил именно прям интенсивно в разных ситуациях. это значит что вполне возможно что есть баги, надо тестить искать их фиксить. в общем НЕ НАДО ЭТО КОПИПАСТИТЬ ЭТО ПОКАЗАТЕЛЬНЫЙ КОД ДЕЛАЙ СВОЙ ПРОСТО ЮЗАЙ ЭТОТ КАК НЕКИЙ ПРИМЕР ПОТЕНЦИАЛЬНОГО КОДА)
C++:
//VVV SHITCODE!!!!
static_assert(false, "SHITCODE!!!!");
class EntityRange 
    {
    public:
        const CGameEntitySystem* entsystem{};
        EntityIndex_t highest{};
        class sentinel {};
        class iterator
        {
            const CGameEntitySystem* entsystem{};
            EntityIndex_t highest{};
            EntityIndex_t current{ -1 };
            C_BaseEntity* ent{};
        public:
            bool IsValid() const noexcept
            {
                return ent != nullptr;
            }

            using iterator_concept = std::forward_iterator_tag;
            using iterator_category = std::input_iterator_tag;
            using difference_type = std::ptrdiff_t;
            using value_type = C_BaseEntity&;

        private:
            void _increment() noexcept
            {
                if (current >= highest)
                    ent = nullptr;
                else
                {

                    ent = entsystem->_GetEntityByIndex(++current);
                    while (!ent && current < highest)
                    {
                        ent = entsystem->_GetEntityByIndex(++current);
                    }
                }
            }
        public:
            iterator(const CGameEntitySystem* sys, const EntityIndex_t& _highest) 
                : entsystem{ sys }, highest{ _highest }
            {
                if (!entsystem)
                    throw std::runtime_error{"EntityRange::iterator::iterator -> nullptr entsystem!"};
                if(!highest.IsValid() || highest >= ENTITYSYSTEM_CAPACITY)
                    throw std::runtime_error{ "EntityRange::iterator::iterator -> invalid highest index!" };

                _increment();
            }

            auto& operator++() noexcept
            {
                _increment();
                return *this;
            };
            auto operator++(int) noexcept
            {
                iterator copy{ *this };
                this->iterator::operator++();
                return copy;
            };

            value_type operator*() const
            {
                if(!ent)
                    throw std::runtime_error{ "EntityRange::iterator -> had nullptr entity somehow!" };
                return *ent;
            }
            auto operator->() const
            {
                return &operator*();
            }
        };

        friend bool operator==(const iterator& it,
            const sentinel&) noexcept
        {
            return !it.IsValid();
        }
    public:
        iterator begin() const
        {
            return iterator{ entsystem, highest };
        }
        sentinel end() const noexcept
        {
            return {};
        }
    };

    auto GetEntities() const noexcept
    {
        return EntityRange{ this, GetHighestIndex() };
    }
юз например
C++:
for (auto& entity : entsys.GetEntities())
    Logger::LogInfo("%d ] %p %s\n", entity.GetIndex(), &entity, entity.GetName().data());
 
Начинающий
Статус
Оффлайн
Регистрация
30 Мар 2020
Сообщения
326
Реакции[?]
24
Поинты[?]
12K
Та проблема была вся в i++ , стоит немного почитать об этом, даже и не знал что есть что-то такое как "++i"
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
781
Реакции[?]
331
Поинты[?]
63K
Та проблема была вся в i++ , стоит немного почитать об этом, даже и не знал что есть что-то такое как "++i"
++i юзай везде по дефолту(не токо в плюсах в джаве в джаваскрипте во всех нормальных языках собсна такое)
i++ юзай токо когда тебе нужно предыдущее значение
я не знаю хули традиционно так сложилось что хелло ворлд фор цикл это
for(int i = 0; i < 123; i++)
по факту должно быть
for(int i = 0; i < 123; ++i)
потому что i++ создает копию(до модификации), модифицирует оригинал, и возвращает эту старую копию(в итоге ты получаешь старое значение). ++i же возвращает само значение i(уже модифицированное)
ну и не забудь свое условие то изменить
i < EntitySystem->GetHighestEntityIndex();
=>
i <= EntitySystem->GetHighestEntityIndex();
 
Сверху Снизу