Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hooking specific procedures in existing scripts #131

Closed
burner1024 opened this issue Jan 16, 2018 · 24 comments
Closed

Hooking specific procedures in existing scripts #131

burner1024 opened this issue Jan 16, 2018 · 24 comments

Comments

@burner1024
Copy link
Contributor

Would it be possible to add a function to hook into a specific procedure of an existing script?
For example, if I want to allow Sulik to open the jammed door in Vault 8, looks like the only option is vivltdor recompilation.

I'm thinking about something like

procedure start begin
  if game_loaded then begin
    override_proc("vivltdor", "Node002","my_proc")
  end
end
...
procedure my_proc begin

in a global script.

That would allow mods to be less intrusive and more compatible with each other, leaving the original files intact.

@FakelsHub
Copy link
Contributor

A good idea, but probably not technically feasible.

@phobos2077
Copy link
Collaborator

phobos2077 commented May 30, 2018

I don't see anything wrong in recompiling the door script. If you want mod to be compatible - just distribute them with source codes, then anyone can just merge it and compile the whole thing. I think somebody already tried this approach, you can automatically extract an existing .int file, decompile it, merge in the mod and then recompile back. It's just a matter of making such a tool (or as part of a mod manager). int2ssl can decompile any script in a predictive way, and if it fails - you can always fix it (it's on github under falltergeist group, or you can use my fork). You can use almost any decent C++ compiler to build it now, since @alexeevdv made it cross platform.

Fallout scripts were not implemented in a modular way at all and global scripts are not the best way to hack around this flaw. They are meant to adjust the overall gameplay systems, not specific characters and locations.

@FakelsHub
Copy link
Contributor

FakelsHub commented May 31, 2018

Как-то вы узко мыслите - одной лишь декомпиляцией).
Прелесть этой возможности в том, что можно переопределять процедуры в скриптах, к примеру имеется оригинальный скрип который кем-то изменён для нужд какого то мода, и есть наш скрипт который должен переопределить в нем процедуру, не затрагивая изменения сделанные кем-то в этом скрипте, при этом сохраняется возможность изменить процедуру и в оригинальном не тронутом скрипте. Как видим сохраняется совместимость, без лишних файлов.

Конечно эта возможность будет мало используемая, но я уже сейчас вижу где бы я ее применил.
В общем когда я разберусь в системе скриптов, я обязательно добавлю эту возможность. :-)

@burner1024
Copy link
Contributor Author

That someone is me, I believe. The issue with recompiling is that it has to be scripted itself. And since I'm only one who got that working, it goes to show that "just merge and compile" is not that trivial. And when doing it manually, it's going to result in separate bundles for different bases, which ruins the point.

I'm not going to insist on this, just want to clarify the reasoning.

@phobos2077
Copy link
Collaborator

phobos2077 commented Jun 3, 2018

@FakelsHub вам по сути нужен ООП которого нет в SSL - наследовать классы и переопределять методы... То что вы хотите сделать по сути хакерство. Узко мыслите как раз вы.
Если вам понадобилось добавить код в функцию написанную кем-то, вы в любом случае привязываетесь к этому коду. Например в каком порядке нужно выполнять код - сначала оригинальная функция, затем дополнительный код? Или сначала дополнительный, потом оригинальный? Или где-то между? Как вы себе представляете это реализовать?

Когда у вас такие жесткие зависимости одного кода от другого, тут никак не обойтись без перекомпиляции и заточки под каждую "платформу" с которой вы хотите совместить ваш "мод-плагин".

В качестве примера нормального решения можно было бы написать систему событий средствами SSL и в той функции которую нужно расширить - добавить вызов "события" (см. шаблон Делегат). В SSL кстати уже есть функции для подписки на события, но только глобальные (вроде). Я бы в эту сторону покопал чем прикручивать очередное хакерство которое только добавит вам головной боли, багов и усложнит поддержку.

PS: старайтесь искать подобающее решение для задачи, прежде чем пытаться идти "в лоб". Тот факт что весь sfall это набор хаков, не значит что любую задачу нужно решать ими. При помощи хаков построена платформа для более удобного кодинга. Сам код лучше писать традиционными способами.

@burner1024
Copy link
Contributor Author

А каким образом добавить вызов события в этой схеме, все также рекомпиляцией?

@FakelsHub
Copy link
Contributor

FakelsHub commented Jun 3, 2018

Если вам понадобилось добавить код в функцию написанную кем-то, вы в любом случае привязываетесь к этому коду.

нет, ты не совсем понял, тут идет речь о полном переопределении метода(процедуры) не знаю есть ли в с++ виртуальные методы, вот в С# есть такое их можно переопределять естественно переопределяется весь кусок метода, а не часть какая-то...

Например в каком порядке нужно выполнять код - сначала оригинальная функция, затем дополнительный код?

...при этом переопределенный код не уже выполняется

@burner1024
Copy link
Contributor Author

@FakelsHub не собрался еще с силами для этого?

@FakelsHub
Copy link
Contributor

пока нет, мало знаний о системе скриптов - как они выполняются.

@burner1024
Copy link
Contributor Author

Bumping... See no way to properly implement generic unlimited party without this. Turns out that while most party members check requirements inside the dialog system, Dogmeat checks them first, and only then enters dialog system.
I was thinking about using mouseclick hook instead, but it's not suitable, as there are actions other than dialog.

@FakelsHub
Copy link
Contributor

Смотрел твой скрипт, ничего не понял. :-)
Ты отсоединяешь всех партийцев при входе в диалог, а потом присоединяешь обратно при выходе, так?

@burner1024
Copy link
Contributor Author

так

@FakelsHub
Copy link
Contributor

В общем я посмотрел можно сделать, крючек для перехвата стандартных процедур.
Думаю в этой версии сделаю.
Но это нет то, о чем ты писал в самом начале, для кастомных процедур, слишком сложно это.

@NovaRain
Copy link
Collaborator

NovaRain commented Sep 3, 2019

Like a HOOK_RUNSTDPROCS with an argument of the standard procedure about being executed?

@FakelsHub
Copy link
Contributor

Yes.

@FakelsHub
Copy link
Contributor

Dogmeat checks them first, and only then enters dialog system.

Догмит также проверят в диалоге, но HOOK_GAMEMODE* срабатывает уже после того как диалог отработал, и игра находится в режиме диалога (ожидает от игрока ответы).

Dogmeat will also check this in the dialog, but HOOK_GAMEMODE* is triggered after the dialog procedure has worked out - the game is in standby mode from the player for answers.

@burner1024
Copy link
Contributor Author

burner1024 commented Sep 4, 2019

Dogmeat will also check this in the dialog, but HOOK_GAMEMODE* is triggered after the dialog procedure has worked out - the game is in standby mode from the player for answers.

Looking at this again, it appears I was mistaken. Not sure how that could happen, sorry.

But then, why HOOK_GAMEMODE is triggered after the procedure? And why it works properly for the other party members?

@NovaRain
Copy link
Collaborator

There will be a HOOK_STDPROCEDURE in 4.2 that runs before most of the standard script procedures (except start, map_p_update, critter_p_proc, the last two would cause performance issue due to engine runs them repeatedly in background, especially critter_p), so you should be able to run your mod before talk_p_proc. Kudos to Mr.Stalin.

@burner1024
Copy link
Contributor Author

That's awesome, please let me know when there's a test build available.

@NovaRain
Copy link
Collaborator

NovaRain commented Sep 11, 2019

@burner1024
Copy link
Contributor Author

I'm unable to get this to work. It seems that talk_handler is never triggered.

@NovaRain
Copy link
Collaborator

NovaRain commented Oct 10, 2019

I'm unable to get this to work. It seems that talk_handler is never triggered.

The test script runs before talking to someone:

procedure start begin
   if game_loaded then begin
      register_hook_proc(HOOK_STDPROCEDURE, hook_test1);
   end
end

procedure hook_test1 begin
   variable
      proc := get_sfall_arg,
      selfObj := get_sfall_arg,
      srcObj := get_sfall_arg;

   if (proc == talk_proc) then begin
      display_msg("Talks to " + obj_name(selfObj) + ".");
   end
end

I don't think there's a source_obj for talk_proc, since only the player can really "talk to" someone.

@FakelsHub
Copy link
Contributor

source in this case will be null.
it didn’t even help to localize your error in the presence of a meaningless debugging message. :-)

@burner1024
Copy link
Contributor Author

Sorry for false alarm. It appears I've been using some beta build. File version was 4.2.0, that confused me. As I re-downloaded the latest release, the problem disappeared.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants