Those are logical OR, not bitwise OR. The compiler determines that "weapon" is a non-null pointer, so you have [some boolean] || true, which evaluates to true, short circuiting the final condition.
However, it then will execute [true | false] | "weapon". "weapon" is not going to be nullptr, therefor, you are bitwise ORing a [true | false] (generally represented as 0x1 and 0x0) against a guaranteed non-nullptr value, giving you a value that is guaranteed to NOT be 0. You then do it again with "the weapon".
To nitpick, the user could type something ambiguous, like: "a magical weapon". In this case the program would behave differently if it checked for the presence of "weapon" or "magic" first.
However, judging by the the set of strings, I wouldn't be surprised if one could get away withif (attack.find("weapon") != std::string::npos)
I think your code behaves reasonably for this, but it is nice to be aware of such edge cases.